这篇博客承接于上一篇博客:【JavaSE系列】第七话 —— 类和对象(1)
🚗目录🚗
🚓七、封装
🚒🚒🚒注意一
🚚🚚🚚注意二
🚜🚜🚜8.5.1 就地初始化
🛹🛹9.3 构造代码块
🚲🚲9.4 静态代码块
🪂🪂10.1 实例内部类
🚁🚁🚁10.1.1 什么是 实例内部类
🚀🚀🚀10.1.2 如何去实例化内部类对象
⛵⛵⛵10.1.3 实例内部类当中 不能定义 静态的成员变量
💺💺💺10.1.4 实例内部类当中,成员变量和外部类成员变量重名
🛬🛬🛬10.1.5 实例内部类 所演示的代码
🚢🚢🚢10.2.1 什么是 静态内部类
🗼🗼🗼10.2.2 如何实例化静态内部类
🏰🏰🏰10.2.3 如何去访问静态内部类
🛸🛸🛸10.3 匿名内部类
🌁总结
七、封装
7.1 封装的概念
面向对象程序 三大特性(注意 是三大特性,而不是三个特性,可能还有第四个,第五个,......,第n个特性):封装、继承、多态;
而 类和对象阶段,主要研究的就是 封装 特性;
那么什么是封装呢?简单来说就是 套壳屏蔽细节。
举个小例子来说明一下 到底什么是封装:
比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等等,让用户来和计算机进行交互,完成日常事务;
但实际上,电脑正真工作的却是CPU、显卡、内存等一些硬性原件;
对于计算机使用者而言,不用关心 内部核心部件,比如主线板上线路是如何布局的,CPU内部是如何设计的等等,他们只需要知道,怎么去开关机、怎么通过键盘和鼠标 与计算机进行交互即可;
因此 计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘、插孔等等,让用户可以与计算机进行交互即可。
封装:将数据和操作数据的方法进行有机结合,隐藏 对象的属性和实现细节,仅对外公开接口来和对象进行 交互。
7.2 访问修饰限定符
那么,应该怎么样对 数据以及操作数据的方法 来进行封装呢?
这就涉及到了四个访问修饰限定符:public、private、protected、default 。
这个知识点博主把单独分享了出来,
大家感兴趣的话,可以点击下面的传送:
八、static成员
8.1 再谈Student类
首先创建对象student1、student2,并且每个对象都有各自的 name、age、score等信息,来对不同的对象进行描述的:
public class Student {
//......
public String name;
public int age;
public double score;
public String classes;
//......
public static void main(String[] args) {
Student student1 = new Student("bit",18,100);
Student student2 = new Student("张三",19,100);
}
那么,通过打断点的形式,我们可以知道 每个对象所存储的数据:
假设三个同学是同一个班的,即:在同一间教室上课,那么有没有一种办法,可以同时来保存他们在同一间教室上课这个信息呢......
在Student类中定义的成员变量,每个对象中都会包含一份,应为需要使用这些信息来描述具体的学生;
而现在要表示学生上课的教室,这个教室的属性 并不需要每个学生对象中都存储一份,而是让每一位学生所共享的;
在Java中,被static修饰的成员,称之为 静态成员(类成员),其不属于某一个具体的对象,而是所有的对象所共享的。
8.2 static修饰成员变量
static修饰的成员变量,称为 静态成员变量;
静态成员变量 的最大特性:不属于某个具体的对象,是所有对象所共享的。
【静态成员变量的静态属性】
- 不属于某个具体的对象,是类的属性,所有对象所共享的,不存储在某个对象的空间中;
- 即可以通过对象访问,也可以通过类名访问,不过一般更加推荐使用类名访问(通过对象访问 就像是那个 合法但是不合理);
- 静态成员变量(类变量) 存储在方法区中;
- 生命周期伴随类的一生(即:随类的创建而创建,随类的销毁而销毁)。
8.3 static修饰成员方法
一般类中的数据成员 都设置为private,而成员方法设置为public;
那设置之后,Student类中的classes属性 如何在类外访问呢?
【静态方法特性】
- 不属于某个具体的对象,是类方法;
- 可以通过对象调用,也可以通过 类名.静态方法名(......) 方式调用,当然,也还是更推荐使用 类名.静态方法名(......) 来调用,通过对象调用 就是“合法但是不合理”;
- 静态方法 没有隐藏的this引用参数,因此不能在静态方法中 访问任何非静态成员变量;
- 静态方法中不能调用 任何非静态方法,因为非静态方法有this参数,在静态方法中 调用时无法传递this引用。
8.4 static还需要注意的地方
注意一:
class Student{
public String name;
public int age;
public double score;
public static String classes;
public static void func(){
System.out.println("这个是一个静态的成员方法!!!!!!");
}
}
public class TestDemo {
public static void main(String[] args) {
Student student1 = null;
student1.classes = "Java";
System.out.println(student1.classes);
}
}
如果没有看编译结果的话,很多人的第一反应是:会发生空指针异常;
但是,正确的编译结果是:
其实原因是这样的:
在实际生活中,我们也不会这样去访问的(这样是合法不合理的),乖乖的用类名去访问就可以了。
注意二:
在普通的方法里面 加上 静态成员变量(或成员方法,这里只列了成员变量的例子),观察是否可以访问:
在静态的成员方法 里面加上 普通的成员变量(或成员方法,这里只列了成员变量的例子),观察是否可以访问:
//注意二所使用的代码:
class Student{
public String name;
public int age;
public double score;
public static String classes;
public Student(String name) {
this.name = name;
}
public static void func(){
//System.out.println("这个是一个静态的成员方法!!!!!!" + name);
}
public void doClass(){
System.out.println(this.name + "正在上课!"+" 班级:"+classes);
}
}
public class TestDemo {
public static void main(String[] args) {
Student.classes = "Java";
Student student = new Student("张三");
student.doClass();
}
}
8.5 static成员变量初始化
【注意】静态成员变量 一般不会放在构造方法中来初始化,构造方法中初始化的是 与对象相关的实例属性;
静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。
8.5.1 就地初始化
就地初始化 指的是:在定义时直接给出初始值:
class Student{
public String name;
public int age;
public double score;
public static String classes = "Java";
//......
}
8.5.2 静态代码块初始化
在学习这一部分内容的时候,还是需要来介绍一下什么是代码块......
九、代码块
9.1 代码块概念 以及分类
使用 {} 定义的一段代码称为代码块。
根据代码块定义的位置 以及关键字,又可分为以下四类:
- 实例代码块 / 构造代码块;
- 静态代码块;
- 本地代码块 / 普通代码块(用不到);
- 同步代码块(目前用不到)。
9.2 普通代码块
普通代码块:定义在方法中的代码块:
9.3 构造代码块
构造代码块:定义在类中的代码块(不加修饰符),也叫:实例代码块。
class Student2 {
public String name;
public int age;
public double score;
public Student2(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
System.out.println("调用带有3个参数的构造方法!");
}
{
System.out.println("实例代码块!!!!!!");
}
public static void main(String[] args) {
Student2 student = new Student2("张三",19,100);
}
}
9.4 静态代码块
使用static定义的代码块 称为静态代码块;
一般用于初始化静态成员变量。
【注意】如果有多个静态代码块,那么执行的顺序和定义的顺序有关;定义在后面的 静态代码块 会把 定义在前面的 给覆盖掉(当然,只是赋值覆盖,就相当于把两个 静态代码块连起来,然后去覆盖,像打印的就不会覆盖了):
class Student2 {
public String name;
public int age;
public double score;
public static String classes;
public Student2(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
System.out.println("调用带有3个参数的构造方法!");
}
@Override
public String toString() {
return "Student2{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
",班级= " + classes +
'}';
}
{
System.out.println("实例代码块!!!!!!");
}
static {
classes = "Java_1";
System.out.println("静态代码块!!!!!!");
}
static {
classes = "Java_2";
System.out.println("静态代码块!!!!!!");
}
public static void main(String[] args) {
Student2 student = new Student2("张三",19,100);
System.out.println(student);
System.out.println("============================================");
Student2 student2 = new Student2("李四",19,100);
System.out.println(student2);
}
}
十、内部类
内部类也是一种类,其重点在于内部二字;
在一个类的内部 定义的类,叫做 内部类。
内部类 可以分为以下几种:
- 实例内部类;
- 静态内部类;
- 匿名内部类。
所以说,以后 如果说内部类的时候,需要带上前缀(不同的内部类,性质、使用方式等等都是有区别的)。
10.1 实例内部类
10.1.1 什么是 实例内部类
class OuterClass {
//普通成员变量(实例成员变量)
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//class InterClass 这个类就叫做 实例内部类
}
}
10.1.2 如何去实例化内部类对象
//外部类名.内部类名 变量 = 外部类对象的引用.new 内部类名();
10.1.3 实例内部类当中 不能定义 静态的成员变量
如果要定义,必须是 编译的时候就要确定的值(即:必须是 static finna的)(内部类里面内部类里面内部类里面):
如果实在内部类外面定义,那就肯定是编译错误:
10.1.4 实例内部类当中,成员变量和外部类成员变量重名
10.1.5 实例内部类 所演示的代码
class OuterClass {
//普通成员变量(实例成员变量)
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
/**
* 实例内部类
*/
class InnerClass {
public int data1 = 1000;
public int data4 = 40;
public int data5 = 50;
public static final int data6 = 60;//常量-》编译的时候,就已经确定这个值是几了
//内部类里面不可以有静态方法
// public static void funcStatic(){
//
// }
public InnerClass(){
System.out.println("InnerClass的构造方法!!!!!!");
}
public void method(){
System.out.println("Java:"+OuterClass.this.data1);
System.out.println(data2);
System.out.println(data3);
System.out.println(data4);
System.out.println(data5);
System.out.println(data6);
System.out.println("InnerClass的一个method方法!!!!!!");
}
}
public void methodOut(){
//static final int c = 10;
}
}
public class TestDemo {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.method();
}
public static void main1(String[] args) {
OuterClass outerClass = new OuterClass();
System.out.println(outerClass.data1);
//外部类名.内部类名 变量 = 外部类对象的引用.new 内部类名();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
OuterClass.InnerClass innerClass1 = new OuterClass().new InnerClass();
//new OuterClass():匿名对象:一般在使用1次的时候(每一次使用都要new一个对象)
// System.out.println(new OuterClass().data1);
// System.out.println(new OuterClass().data2);
}
}
10.2 静态内部类
10.2.1 什么是 静态内部类
被static修饰的内部类叫做 静态内部类。
class OuterClass2 {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
static class InnerClass {
//这个类就叫做静态内部类
}
}
10.2.2 如何实例化静态内部类
//外部类名.静态内部类名 变量 = new 外部类名.静态内部类名
10.2.3 如何去访问静态内部类
10.2.4 静态内部类 所演示的代码
class OuterClass2 {
public int data1 = 10;
public int data2 = 20;
public static int data3 = 30;
public void method() {
System.out.println("OuterClass2::method()");
}
static class InnerClass {
//这个类就叫做静态内部类
public int data4 = 40;
private int data5 = 50;
public static int data6 = 60;
OuterClass outerClass = new OuterClass();
public InnerClass() {
System.out.println("InnerClass的构造方法!!!!!!");
}
public void method() {
System.out.println(outerClass.data1);
System.out.println(outerClass.data2);
System.out.println(data3);
System.out.println(data4);
System.out.println(data5);
System.out.println(data6);
System.out.println("innerclass的method的方法!!!!!!");
}
}
}
public class TestDemo2 {
public static void main(String[] args) {
//调用的时候不需要外部类对象,所以 静态内部类使用的频率会比较多一点
OuterClass2.InnerClass innerClass = new OuterClass2.InnerClass();
}
}
10.3 匿名内部类
这部分内容等到后面 接口 的内容再详细介绍嗷......
总结
花费了好几天的时间总结了关于 类与对象 的知识 到此就结束了;
当然,还有一些不足的地方;
后期也要修修改改;
希望大家收获满满呀!!!!!!
如果铁铁们可以一键三连那就更棒了,特别特别感谢 ୧(๑•̀⌄•́๑)૭ 。