封装
封装
- 封装是将数据(变量)和操作(方法或函数)捆绑在一起的机制,使得对象的内部细节对外部是隐藏的,只有通过公共接口才能访问。
- 封装提供了访问控制,可以限制对对象内部数据的直接访问,从而保护数据的完整性和安全性。
- 通过封装,可以隐藏实现的细节,使得代码更易于理解和维护,并且提高了代码的可重用性。
类:类中定义对象的属性数据(成员变量),方法(成员方法)
类第一次使用时会加载到方法区
Java 内存的结构分析
栈: 一般存放基本数据类型(局部变量)
堆: 存放对象(Cat cat , 数组等)
方法区:常量池(常量,比如字符串), 类加载信息
对象
- 从模板中创建的具体实例,实例是数据的打包
- 新建实例时,在堆内存中新分配内存空间给这个实例
成员变量与局部变量区别
- 定义的位置不一样
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中
- 作用范围不一样
局部变量:只有方法当中才可以使用,出了方法就不能再用
成员变量:整个类全都可以通用
- 默认值不一样
局部变量:没有默认值,如果要想使用,必须手动进行赋值
成员变量:如果没有赋值,会有默认值,规则和数组一样
- 内存的位置不一样
局部变量:位于栈内存
成员变量:位于堆内存
- 生命周期不一样
局部变量:随着方法进栈而诞生,随着方法出栈而消失
成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失
引用变量
保存一个实例的内存地址(引用变量保存在栈),引用变量的特殊值:null 不保存任何实例的内存地址

this关键字
特殊引用,引用当前对象的地址
this:构造方法之间的调用,必须是首行代码,如果有多个构造方法,会通过this(…)调取下面的所有构造方法,完成赋值。
注意
- this不能在静态方法中使用
- 当方法的局部变量和类的成员变量重名的时候,根据“就近原则”,优先使用局部变量。
- 如果需要访问本类当中的成员变量,需要使用格式:this.成员变量名
- 通过谁调用的方法,谁就是this。
1 |
|
static 关键字
static
关键字用于在Java中创建类级别的成员,这些成员不依赖于类的实例而存在,可以直接通过类名访问。
从概念上讲,类变量所使用的内存都应当在 方法区 中进行分配。不过有一点需要注意的是:JDK 7 之前,HotSpot 使用永久代来实现方法区的时候,实现是完全符合这种逻辑概念的。 而在 JDK 7 及之后,HotSpot 已经把原本放在永久代的字符串常量池、静态变量等移动到堆中,这个时候类变量则会随着 Class 对象一起存放在 Java 堆中。

静态变量
- 当 static 修饰成员变量时,该变量称为类变量。
- 该类的每个对象都共享同一个类变量的值。
- 任何对象都可以更改该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。
- 随着类的加载而加载的,且只加载一次(JDK1.7之后随着Class对象加载到堆区)。
- 存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。
- 它优先于对象存在,所以可以被所有对象共享
静态方法
- 一旦使用static修饰成员方法,那么这就成为了静态方法。
- 静态方法不属于对象,而是属于类的。
- 如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。
- 如果有了static关键字,那么不需要创建对象,直接就能通过类名称来使用它。
无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。
静态变量:类名称.静态变量
静态方法:类名称.静态方法()
注意事项:
- 静态方法不能直接访问非静态方法。原因:当编译器解析静态方法时,它不需要创建类的实例,因此无法确定要调用的非静态方法是哪个实例的方法。非静态方法的调用需要通过对象的引用来实现,而静态方法中没有当前对象的引用,无法进行非静态方法的调用。
- 静态方法当中不能用this。原因:因为
this
关键字引用的是当前对象的引用,而静态方法没有当前对象的引用。 - 如果需要需要静态方法调用非静态方法,需要通过new 对象.method()的方式调用
静态代码块
定义在成员位置,使用static修饰的代码块{ }。
执行:随着类的加载而执行且执行一次,优先于main方法和构造方法的执行
静态代码块的典型用途:用来一次性地对静态成员变量进行赋值。

final关键字
表示不可改变。可以用于修饰类、方法和变量
final类
被修饰的类,不能被继承
含义:当前这个类不能有任何的子类。
注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写
final方法
被修饰的方法,不能被重写
当final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写。
注意事项:对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾
final变量
被修饰的变量,不能被重新赋值。
对于基本类型来说,不可变说的是变量当中的数据不可改变
对于引用类型来说,不可变说的是变量当中的地址值不可改变
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。
- 由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了。
- 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值,二者选其一。
- 必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。
1 |
|
对于基本类型来说,不可变说的是变量当中的数据不可改变
对于引用类型来说,不可变说的是变量当中的地址值不可改变
1 |
|
四种权限修饰符

可见,public具有最大权限。private则是最小权限。 编写代码时,如果没有特殊的考虑,建议这样使用权限:
成员变量使用 private ,隐藏细节。
构造方法使用 public ,方便创建对象。
成员方法使用 public ,方便调用方法。
小贴士:不加权限修饰符,其访问能力与default修饰符相同
private修饰符
- private是一个权限修饰符,代表最小权限。
- 可以修饰成员变量和成员方法。
- 被private修饰后的成员变量和成员方法,只在本类中的方法才能访问
间接访问
private成员变量,就是定义一对儿Getter/Setter方法
必须叫setXxx或者是getXxx命名规则。
对于Getter来说,不能有参数,返回值类型和成员变量对应;
对于Setter来说,不能有返回值,参数类型和成员变量对应。
1 |
|
内部类
成员内部类
成员内部类的定义格式:
1 |
|
访问特点
- 内部类可以直接访问外部类的成员,包括私有成员。
- 外部类要访问内部类的成员,必须要建立内部类的对象。
如何使用成员内部类?有两种方式:
- 在外部类的方法当中,直接new 内部类;然后main使用这个外部类的方法
- 公式法:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称()
1 |
|
1 |
|
局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
1 |
|
局部内部类要访问局部变量,为什么该变量必须是final?
备注:从Java 8+开始,只要局部变量事实不变(即不改变该局部变量的值),那么final关键字可以省略。
原因:
- new出来的对象在堆内存当中。
- 局部变量是跟着方法走的,在栈内存当中,方法运行结束之后,立刻出栈,局部变量就会立刻消失。
- 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失,当内部类对象要使用局部变量时就会出错
- 因为局部内部类的生命周期比方法的局部变量长,所以要确保方法内的局部变量不改变
1 |
|
那为什么添加final修饰的局部变量,就可以被局部内部类引用呢?
若定义为final,则java编译器则会在内部类内生成一个外部变量的拷贝,而且可以既可以保证内部类可以引用外部属性,又能保证值的唯一性
也就是拷贝了一个变量的副本,提供给局部内部类,这个副本的生命周期和局部内部类一样长,并且这个副本不可以修改,保证了数据的同步
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。
1 |
|
new代表创建对象的动作
接口名称就是匿名内部类需要实现哪个接口
{…}这才是匿名内部类的内容
另外还要注意几点问题:
匿名内部类,在【创建对象】的时候,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样的话,那么就需要使用单独定义的实现类了。
匿名对象,在【调用方法】的时候,只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
强调:匿名内部类和匿名对象不是一回事
1 |
|
静态内部类
静态内部类是指被声明为 static 的内部类。在 Java 中,类可以嵌套在其他类中,被嵌套的类称为内部类。静态内部类与普通内部类的区别在于,静态内部类可以直接通过外部类的类名进行访问,而不需要先创建外部类的实例。
以下是静态内部类的一些特点和用法:
静态内部类的声明:静态内部类使用 static 关键字进行声明,它可以访问外部类的静态成员和方法,但不能访问外部类的非静态成员和方法。静态内部类的声明形式如下:
1
2
3
4
5public class OuterClass {
static class StaticInnerClass {
// 静态内部类的成员和方法
}
}访问方式:静态内部类可以直接通过外部类的类名进行访问,无需先创建外部类的实例。例如:
1
OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
独立性:静态内部类与外部类之间的关系不像普通内部类那样密切,静态内部类可以独立于外部类而存在,因此它不会持有外部类的引用。
静态内部类的作用:静态内部类通常用于以下情况:
- 帮助组织类和提高代码的可读性,将相关的类放在一起。
- 如果内部类不需要访问外部类的实例变量或方法,可以将其声明为静态内部类,避免与外部类实例的绑定。
- 在外部类的静态方法中使用静态内部类
- 帮助组织类和提高代码的可读性,将相关的类放在一起。
1 |
|