一、Java封装核心知识点
1.1 封装的定义
封装:把对象的属性和行为包装在类中,对外部隐藏实现细节,只对外提供公共访问方式。
一句话总结:隐藏实现,暴露方法,保护数据。
1.2 封装的核心思想
私有化成员变量(用
private修饰,禁止外部直接访问);提供公共的访问方法(
getXxx()取值、setXxx()赋值);在公共方法中可以添加数据校验,保证数据的合法性和安全性。
1.3 封装的实现步骤
实现封装只需3步,代码可直接复制运行:
成员变量使用
private修饰;为每个私有变量提供对应的
get/set方法;通过
get/set方法操作属性,不直接访问私有变量。
完整示例(Student类):
public class Student { // 1. 私有成员变量(private修饰,外部无法直接访问) private String name; private int age; // 2. 为每个私有变量提供get/set方法(公共访问方式) // get方法:获取name的值 public String getName() { return name; } // set方法:给name赋值 public void setName(String name) { this.name = name; } // get方法:获取age的值 public int getAge() { return age; } // set方法:给age赋值,添加数据校验(核心亮点) public void setAge(int age) { // 数据校验:年龄必须在0-150之间,否则提示并拒绝赋值 if(age < 0 || age > 150) { System.out.println("年龄不合理,无法赋值"); return; // 终止方法,不执行后续赋值操作 } this.age = age; } }使用示例(测试封装效果):
public class TestStudent { public static void main(String[] args) { // 创建Student对象 Student stu = new Student(); // 用set方法赋值(正确赋值) stu.setAge(20); stu.setName("张三"); // 用get方法取值 System.out.println("姓名:" + stu.getName()); System.out.println("年龄:" + stu.getAge()); // 测试数据校验(非法赋值,被拦截) stu.setAge(200); // 输出:年龄不合理,无法赋值 System.out.println("非法赋值后的年龄:" + stu.getAge()); // 仍为20 } }运行结果:
姓名:张三 年龄:20 年龄不合理,无法赋值 非法赋值后的年龄:201.4 封装的好处
提高数据安全性:防止外部随意修改私有成员变量,通过校验保证数据合法;
隐藏实现细节:外部只需调用get/set方法,无需关心内部逻辑;
便于维护:修改内部逻辑(如调整校验规则)时,不影响外部调用代码;
可实现数据校验:在set方法中添加条件,过滤非法数据。
1.5 private关键字(封装的关键)
private是Java中最小访问权限修饰符;
被private修饰的成员(变量/方法),只能在本类中访问;
子类、同包其他类、不同包类,都无法直接访问private修饰的成员;
是实现封装的核心:通过private隐藏属性,再通过公共方法暴露访问路径。
1.6 this关键字(封装中常用)
在封装的set方法中,经常会遇到「局部变量与成员变量重名」的问题,此时就需要用this关键字解决,核心作用:
区分成员变量和局部变量重名,this.变量名表示当前对象的成员变量,不加this则遵循就近原则。
经典示例(set方法中使用this):
public void setName(String name) { // this.name:成员变量(Student类的name) // name:局部变量(setName方法的参数) this.name = name; }1.7 封装常考面试题/简答题
问:什么是Java封装? 答:把对象的属性和行为包装在类中,隐藏实现细节,只对外提供公共访问方式(get/set方法),核心是保护数据。
问:封装的好处有哪些? 答:提高数据安全性、隐藏实现细节、便于维护、可进行数据校验。
问:如何实现Java封装? 答:用private修饰成员变量,为每个私有变量提供get/set方法,通过方法操作属性。
问:private关键字的作用? 答:限制访问权限,被修饰的成员只能在本类中访问,是实现封装的关键。
二、get方法与set方法(格式+调用区别)
get和set方法是封装的核心访问方式,格式固定,必须背会,考试/写代码高频使用!
假设私有成员变量为:private int age;,以此为例讲解格式。
2.1 核心格式(必须背)
(1)set方法(赋值)
作用:给私有成员变量赋值/存值;
格式:
public void setXxx(参数类型 参数名) { this.成员变量 = 参数名; };关键特征:有参数,无返回值(void);
示例:
// 给age赋值的set方法 public void setAge(int age) { // 可添加数据校验(可选,非必须,但推荐) if(age < 0 || age > 150) { System.out.println("年龄不合理"); return; } this.age = age; }(2)get方法(取值)
作用:从私有成员变量中取值/拿值;
格式:
public 返回值类型 getXxx() { return 成员变量; };关键特征:无参数,有返回值(返回值类型与成员变量一致);
示例:
// 获取age值的get方法 public int getAge() { return age; }调用格式:对象名.方法名(),赋值用set,取值用get,示例:
Student stu = new Student(); // set方法:赋值(参数是要赋的值) stu.setAge(20); stu.setName("张三"); // get方法:取值(接收返回值,或直接打印) int studentAge = stu.getAge(); // 接收返回值 System.out.println(stu.getName()); // 直接打印2.3 boolean类型的特殊规则(高频考点)
如果私有成员变量是boolean类型(true/false),get方法的命名有特殊规则:
不叫
getXxx(),而是叫isXxx();set方法命名不变,仍为
setXxx()。
示例(boolean类型变量):
public class Student { // boolean类型私有变量 private boolean male; // 是否为男性 // set方法:命名不变 public void setMale(boolean male) { this.male = male; } // get方法:特殊命名,用is开头 public boolean isMale() { return male; } }调用示例:
Student stu = new Student(); stu.setMale(true); // 赋值 System.out.println(stu.isMale()); // 取值,输出true三、就近原则与this关键字详解
就近原则和this关键字,是解决「局部变量与成员变量重名」的核心,也是考试高频考点,两者结合记忆更高效。
3.1 就近原则(定义+示例)
什么是就近原则
当局部变量(方法内定义的变量、方法参数)和成员变量(类中定义的变量)重名时,Java会优先使用「离得更近」的局部变量,这就是就近原则。
经典示例
public class Student { // 成员变量(类中定义) int age = 20; // 成员方法 public void show() { // 局部变量(方法内定义,与成员变量重名) int age = 10; // 就近原则:优先使用局部变量age(10) System.out.println(age); } public static void main(String[] args) { Student stu = new Student(); stu.show(); // 输出:10 } }说明:局部变量age在方法内,离打印语句更近,所以优先使用局部变量的10,而非成员变量的20。
3.2 this关键字的本质与核心作用
this是什么
this是Java中的关键字,代表「当前对象」—— 谁调用当前方法,this就代表谁。
例:stu调用show()方法,this就代表stu对象;stu2调用show()方法,this就代表stu2对象。
this的核心作用
解决「就近原则带来的重名问题」:当局部变量与成员变量重名时,用this.成员变量强制访问成员变量,避免被局部变量覆盖。
经典对比
public class Student { // 成员变量 private int age; // 方法参数(局部变量)与成员变量重名 public void setAge(int age) { // 错误写法:age(局部变量)给自己赋值,成员变量age未改变 age = age; // 正确写法:this.age(成员变量)= age(局部变量) this.age = age; } }说明:
age = age;:左边是局部变量,右边也是局部变量,相当于“自己给自己赋值”,成员变量age始终是默认值0,毫无意义;this.age = age;:左边是成员变量(this.age),右边是局部变量(方法参数),真正实现“给成员变量赋值”。
3.3 就近原则与this的对比(必考)
写法 | 代表的变量 | 遵循的规则 |
|---|---|---|
| 局部变量(方法内/参数) | 就近原则 |
| 成员变量(类中定义) | 强制访问成员变量,不受就近原则影响 |
3.4 this的其他用法
除了区分重名变量,this还有两个常用用法:
(1)调用本类的其他构造方法
格式:this(参数),用于构造方法之间的调用,注意两个关键点:
this(...)必须写在构造方法的第一行;只能在「构造方法」中调用「本类的其他构造方法」,不能在成员方法中调用。
示例:
public class Student { private int age; // 无参构造 public Student() { // 调用本类的有参构造(this(10)),给age赋值为10 this(10); System.out.println("无参构造执行"); } // 有参构造 public Student(int age) { this.age = age; System.out.println("有参构造执行,age=" + age); } public static void main(String[] args) { Student stu = new Student(); // 调用无参构造 } }运行结果:
有参构造执行,age=10 无参构造执行(2)调用本类的成员方法
格式:this.成员方法名(),可省略this(Java会默认补充),但加上this更规范,便于区分。
示例:
public class Student { public void show() { System.out.println("show方法执行"); } public void test() { // 调用本类的show方法,两种写法均可 this.show(); // 推荐,规范清晰 // show(); // 省略this,Java默认补充 } }3.5 核心知识点总结
就近原则:局部变量与成员变量重名时,优先使用局部变量;
this关键字:代表当前对象,核心用来访问成员变量(解决重名)、调用本类构造方法、调用本类成员方法。
四、构造方法
4.1构造方法概述
构造方法(构造器、构造函数):创建对象时,自动调用、用于初始化对象成员变量的特殊方法。
4.2 作用
- 创建对象:
new关键字本质就是调用构造方法。 - 初始化属性:对象一创建就完成赋值,避免手动
set遗漏。
4.3 格式(语法)
[修饰符] 类名(参数列表) { // 初始化代码 }示例:
public class Student { // 成员变量 private String name; private int age; // 无参构造方法 public Student() { System.out.println("无参构造执行"); } // 有参构造方法 public Student(String name, int age) { this.name = name; this.age = age; } }4.4 核心特点(必须记住)
- 方法名与类名完全一致(大小写相同)
- 无返回值类型(连
void都不能写) - 不能 return 具体值(可空
return;) new对象时自动调用,不能手动调用- 支持重载(参数列表不同)
- 默认构造:不写则系统自动提供无参空构造;写任意构造后,默认构造消失
4.5 分类
1. 无参构造方法
- 无参数、方法体可空
- 系统默认提供
public Student() {}2. 有参构造方法
- 带参数,用于直接初始化属性
- 常用:单参、全参
public Student(String name) { this.name = name; } public Student(String name, int age) { this.name = name; this.age = age; }4.6 关键字this(构造中常用)
this.变量:访问本类成员变量(区分局部变量与成员变量)this(参数):调用本类其他构造方法(必须写在第一行)
示例:
public Student() { // 调用全参构造 this("无名氏", 18); } public Student(String name, int age) { this.name = name; this.age = age; }4.7 重载(构造方法重载)
同一个类中:
- 方法名相同(都是类名)
- 参数列表不同(个数、类型、顺序不同)
- 与返回值、修饰符无关
示例:
public Student() {} public Student(String name) {} public Student(int age) {} public Student(String name, int age) {}4.8 注意事项(黑马重点强调)
- 不写构造 →系统默认无参构造
- 写任意构造 →默认无参构造消失
- 若要同时使用无参 + 有参 →必须手动写无参构造
- 构造方法不能被
static/final/abstract修饰 - 构造方法可私有(
private):用于单例模式、工具类(禁止外部创建对象)
4.9 完整代码
class Student { private String name; private int age; // 无参构造 public Student() { System.out.println("无参构造"); } // 全参构造 public Student(String name, int age) { this.name = name; this.age = age; } // Getter/Setter public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // 显示信息 public void show() { System.out.println(name + ", " + age); } } public class StudentDemo { public static void main(String[] args) { // 调用无参 Student s1 = new Student(); s1.show(); // null, 0 // 调用全参 Student s2 = new Student("张三", 20); s2.show(); // 张三, 20 } }4.10 一句话总结
构造方法 =创建对象 + 初始化属性
- 同名、无返回、
new自动调 - 可重载、可用
this - 不写默认有,写了默认无
五,标准javabean类
5.1 什么是 JavaBean
JavaBean 就是符合规范的实体类,用来封装数据。简单理解:专门用来创建对象、存数据的标准类。
5.2 JavaBean 的4 条标准规范
- 类名见名知意,且用大驼峰
- 成员变量私有化(private 修饰)
- 提供无参构造方法
- 提供每一个成员变量对应的 getXxx () /setXxx ()
满足这 4 条,就是标准 JavaBean。
5.3 细节说明
成员变量 private
- 外界不能直接访问,保证数据安全
- 只能通过
get/set操作
必须有无参构造
- 自己写了有参构造,无参构造必须手动写,否则默认无参消失
get/set 方法命名规则
set变量名():给变量赋值get变量名():获取变量的值- 布尔类型特殊:
isXxx()
5.4 标准 JavaBean 代码示例
public class Student { // 1. 成员变量私有 private String name; private int age; // 2. 无参构造 public Student() { } // 3. 有参构造(可选,但开发常用) public Student(String name, int age) { this.name = name; this.age = age; } // 4. get和set方法 public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } }5.5 使用 JavaBean
public class Test { public static void main(String[] args) { // 空参创建 Student s = new Student(); s.setName("张三"); s.setAge(23); System.out.println(s.getName()); System.out.println(s.getAge()); // 有参创建 Student s2 = new Student("李四", 24); } }5.6 重点
- JavaBean只用来封装数据,不写业务逻辑
- 以后框架、项目里的实体类全是这种写法
- IDEA 可以一键生成:
Alt + Insert→ 构造器、getter、setter
六,对象内存图
6.1 Java 内存划分(本节重点)
视频里讲的是5 块内存(本地方法栈,寄存器,栈,方法区,堆),重点关注两块(栈,堆,方法区):
- 栈内存(Stack)
- 存放局部变量(方法里的变量、方法参数)
- 方法进栈执行,方法结束弹栈,变量消失
- 堆内存(Heap)
- 存放new 出来的对象
- 对象里有成员变量
- 有地址值
6.2 单个对象的内存图流程
以代码为例:
Student s = new Student(); s.name = "张三"; s.age = 23; s.show();执行流程:
main方法进入栈new Student()在堆中开辟空间,生成地址值- 栈中的变量
s保存的是堆内存地址(引用) - 通过
s.变量赋值,其实是通过地址找到堆里的成员变量 - 调用
s.show(),show方法进栈执行,执行完毕弹栈
一句话:栈存引用(地址),堆存对象(数据)
6.3 两个对象的内存图
Student s1 = new Student(); Student s2 = new Student();- 两次
new→堆里两个独立对象 - 栈里
s1、s2分别指向不同地址 - 修改
s1的值不会影响s2
6.4 两个引用指向同一个对象(引用传递)
Student s1 = new Student(); Student s2 = s1;- 堆里只有一个对象
s1和s2保存同一个地址值- 通过
s2修改属性,s1访问时也会变 - 这就是引用传递
6.5 成员变量和局部变量在内存中的区别
表格
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 定义位置 | 类中、方法外 | 方法内或方法声明中 |
| 内存位置 | 堆内存 | 栈内存 |
| 生命周期 | 随对象创建而存在,对象被回收而消失 | 方法调用存在,方法结束消失 |
| 初始化值 | 有默认初始化值 | 无默认值,必须手动赋值 |
| 作用域 | 整个类中可用 | 只在当前方法内有效 |
重点强调:
- 成员变量有默认值:
int 0、double 0.0、boolean false、引用 null - 局部变量没有默认值,不赋值不能用
6.6 垃圾回收简单说明
- 堆中的对象,当没有任何引用指向它时,就变成垃圾
- 由GC(垃圾回收器)自动回收,不需要手动处理
6.7 本节核心结论
- 对象存在堆内存中
- 对象的引用变量存在栈内存中
- 多个引用可以指向同一个对象
- 成员变量在堆,局部变量在栈
- 对象通过地址值被使用
七,补充内容:标准数据类型和引用数据类型
7.1 两种数据类型分类
基本数据类型(4 类 8 种)
- 整数:byte、short、int、long
- 浮点:float、double
- 字符:char
- 布尔:boolean
引用数据类型
- 除了基本类型以外,其他都是
- 例如:String、数组、自定义对象(Student、Teacher…)
7.2 核心区别:变量里存的是什么
基本数据类型变量中直接存储数据值
引用数据类型变量中存储的是地址值通过地址指向堆里的真实对象
7.3 赋值与传递的区别(重点)
1. 基本数据类型赋值
int a = 10; int b = a;- 把a 的值复制一份给 b
- a 和 b 相互独立
- 修改 b 不会影响 a
2. 引用数据类型赋值
Student s1 = new Student(); Student s2 = s1;- 把s1 里的地址值复制给 s2
- s1 和 s2 指向同一个对象
- 通过 s2 修改对象内容,s1 访问时也会变
7.4 方法参数传递
1. 基本类型作为参数
- 传递的是值副本
- 方法内部修改,不会影响原来的变量
2. 引用类型作为参数
- 传递的是地址值
- 方法内部通过地址修改对象内容,会影响外面的对象
一句话总结:基本类型传值,引用类型传地址。
7.5 内存区别
- 基本类型变量:数据存在栈内存
- 引用类型变量:
- 变量名(引用)在栈
- 真实对象数据在堆
- 栈里只存地址
7.6 重点
- 基本类型变量里存的是真实数据
- 引用类型变量里存的是地址
- 基本类型赋值:互不影响
- 引用类型赋值:共用同一个对象
- 方法传参规则同上
八,补充内容:this的内存原理
8.1 this 是什么
- this是一个引用,存储的是当前对象的地址
- 哪个对象调用方法,this 就代表哪个对象
- this 可以理解为:“我自己”、“当前对象”
8.2 this 的作用
- 区分成员变量和局部变量重名问题
- 在本类构造方法中调用其他构造方法:
this(...) - 表示当前对象,可作为返回值、参数传递
8.3 this 的内存原理(重点)
- 方法在执行时,会默认传入 this
- this 存在于栈中,保存的是堆里当前对象的地址值
- 谁调用这个方法,this 就指向谁
- 所以
this.xxx访问的就是调用者对象的成员变量
8.4 为什么要用 this?(重名问题)
当局部变量和成员变量同名时:
- 直接写变量名 → 访问局部变量(就近原则)
- 加
this.→ 访问成员变量
示例:
public class Student { private String name; public void setName(String name) { // 等号右边 name 是局部变量 // 等号左边 this.name 是成员变量 this.name = name; } }8.5 this 调用构造方法
- 格式:
this(参数); - 作用:调用本类其他构造方法
- 必须写在构造方法第一行
- 不能互相递归调用(会死循环)
示例:
public Student() { this("无名氏"); } public Student(String name) { this.name = name; }8.6 this 在内存中的表现
- 创建对象:
Student s = new Student(); - 调用方法:
s.setName("张三"); - 进入方法栈,this 保存 s 的地址
this.name就等价于s.name
多个对象调用同一个方法时:
- 每个对象调用时,this 就指向自己
- 所以方法能正确区分是哪个对象的数据
8.7 核心总结
- this 代表当前调用方法的对象
- this 存储的是地址值,在栈中
- 解决变量重名:
this.成员变量 - 调用本类构造:
this(...)必须在第一行 - 谁调用我,我就代表谁
九,补充内容:成员和局部
9.1 定义位置不同
- 成员变量:类中、方法外面
- 局部变量:方法内部或 方法声明上(形参)
9.2 初始化值不同
- 成员变量:有默认值,不赋值也能直接用
- 整数:0
- 浮点:0.0
- 布尔:false
- 引用类型:null
- 局部变量:没有默认值,必须先赋值,再使用
9.3 内存位置不同
- 成员变量:随着对象在堆内存
- 局部变量:随着方法在栈内存
9.4 生命周期不同
- 成员变量:对象创建时出生,对象被垃圾回收时消失
- 局部变量:方法调用时出生,方法执行完毕就消失
9.5 作用域不同
- 成员变量:整个类中都可以使用
- 局部变量:只在当前方法内有效,出了方法就不能用
9.6 命名冲突问题
- 成员变量和局部变量可以同名
- 访问时遵循就近原则:优先使用局部变量
- 想访问成员变量,必须加this.
示例:
public class Student { // 成员变量 int age = 20; public void show() { // 局部变量 int age = 10; System.out.println(age); // 就近:10 System.out.println(this.age); // 成员:20 } }9.7 表格总结
表格
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 定义位置 | 类中、方法外 | 方法内或方法参数 |
| 初始化值 | 有默认值 | 无默认值,必须赋值 |
| 内存位置 | 堆内存 | 栈内存 |
| 生命周期 | 随对象 | 随方法 |
| 作用域 | 整个类 | 当前方法 |
| 重名处理 | 用 this 区分 | 不能重名 |
9.8 总结
- 成员变量:跟着对象走,堆里有默认值
- 局部变量:跟着方法走,栈里没默认值
- 同名就近找,成员要加 this