今日目标
理解封装的意义和作用掌握访问修饰符(public、private、protected、默认)的用法学会用隐藏属性,用
private方法提供访问接口理解
getter/setter关键字的作用
this
一、为什么需要封装?
先看一个没有封装的例子:
public class Person {
String name;
int age; // 年龄是公开的,外部可以直接修改
}
// 测试类
public class TestPerson {
public static void main(String[] args) {
Person p = new Person();
p.age = -20; // 年龄被设置为负数,这在现实中是不合理的!
System.out.println("年龄:" + p.age); // 输出:-20
}
}
问题在于:外部可以直接修改属性,甚至设置不合理的值(如负数),导致数据不安全。
age
封装的解决思路:
将属性隐藏起来(不让外部直接访问)。提供公共方法,控制对属性的访问(比如设置年龄时检查合法性)。
二、访问修饰符:控制访问权限
Java 通过访问修饰符来控制类、属性、方法的访问范围,共有 4 种:
| 修饰符 | 同一类中 | 同一包中 | 不同包的子类 | 不同包的非子类 | 常见用途 |
|---|---|---|---|---|---|
|
✔️ | ❌ | ❌ | ❌ | 隐藏类的属性或内部方法 |
(不写) |
✔️ | ✔️ | ❌ | ❌ | 同包内可见的工具类 / 方法 |
|
✔️ | ✔️ | ✔️ | ❌ | 允许子类访问的属性 / 方法 |
|
✔️ | ✔️ | ✔️ | ✔️ | 对外暴露的接口(类 / 方法) |
核心原则:属性通常用隐藏,方法根据需要用
private(对外暴露)或
public(内部使用)。
private
三、封装的实现:
private +
getter/setter
private
getter/setter
1. 用
private修饰属性(隐藏数据)
private
public class Person {
private String name; // 私有属性,外部不能直接访问
private int age; // 私有属性
}
此时,外部直接访问会报错(编译不通过),达到了隐藏数据的目的。
p.age
2. 提供
public的
getter和
setter方法(控制访问)
public
getter
setter
:获取属性值(命名格式:
getter)。
public 数据类型 get属性名():设置属性值(命名格式:
setter),可以在方法中添加数据校验。
public void set属性名(参数)
示例:完善 Person 类
public class Person {
private String name;
private int age;
// name的getter:获取姓名
public String getName() {
return name;
}
// name的setter:设置姓名
public void setName(String n) {
name = n; // 简单赋值(也可添加校验,如非空判断)
}
// age的getter:获取年龄
public int getAge() {
return age;
}
// age的setter:设置年龄(添加合法性校验)
public void setAge(int a) {
if (a < 0 || a > 150) { // 年龄不能小于0或大于150
System.out.println("年龄不合法!默认设置为18");
age = 18; // 赋默认值
} else {
age = a; // 合法则赋值
}
}
}
3. 外部通过
getter/setter访问属性
getter/setter
public class TestPerson {
public static void main(String[] args) {
Person p = new Person();
// 不能直接访问私有属性(编译报错)
// p.age = 20;
// 通过setter设置属性
p.setName("张三");
p.setAge(-20); // 年龄不合法!默认设置为18
// 通过getter获取属性
System.out.println("姓名:" + p.getName()); // 张三
System.out.println("年龄:" + p.getAge()); // 18
}
}

封装的好处:
数据安全:通过控制属性的赋值,避免不合理数据。灵活性:如果后期需要修改校验规则(如年龄上限改为 120),只需修改
setter方法,外部调用者无需改动。隐藏实现细节:外部只需要知道 “如何用”(调用方法),不需要知道 “内部如何实现”。
setter
四、
this关键字
this
当方法的参数名与类的属性名相同时,会出现 “命名冲突”,此时用关键字区分属性和参数。
this
代表当前对象(调用该方法的对象)。
this
示例:用
this解决命名冲突
this
public class Person {
private String name;
private int age;
// 参数名与属性名相同(name、age)
public void setName(String name) {
// this.name 指当前对象的属性name
// 后面的name 指方法的参数name
this.name = name;
}
public void setAge(int age) {
if (age < 0 || age > 150) {
this.age = 18; // this.age 指属性age
} else {
this.age = age;
}
}
// 构造方法中也可以用this
public Person(String name, int age) {
this.name = name; // 区分属性和参数
this.age = age;
}
}
示例:
Person.java
package study_7_2;
public class Person {
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int age(){
return age;
}
}
testPerson.java
package study_7_2;
public class testPerson {
public static void main(String[] args){
Person p1 = new Person("张三",18);
System.out.println(p1.getName());
System.out.println(p1.age());
}
}

this的其他用法:
this
调用本类的其他构造方法(,必须放在构造方法的第一行):
this(参数)
public class Person {
private String name;
private int age;
// 无参构造
public Person() {
this("默认姓名", 18); // 调用有参构造,简化代码
}
// 有参构造
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
一、构造方法的作用
构造方法用于创建对象时初始化对象的属性,是 Java 中创建对象的 “专属方法”。
无参构造(
public Person()):
public Person()
当创建对象时不传递任何参数时,会调用这个构造方法。它内部通过 调用了有参构造,目的是复用有参构造的逻辑,给对象设置默认的姓名和年龄(“默认姓名”、18)。
this("默认姓名", 18)
有参构造(
public Person(String name, int age)):
public Person(String name, int age)
当创建对象时传递姓名和年龄参数时,会调用这个构造方法,直接给对象的 和
name 属性赋值,实现自定义初始化。
age
Person.java
package study_7_3;
public class Person {
private String name;
private int age;
public Person(){
this("默认姓名", 18);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
TestPerson.java
package study_7_3;
public class TestPerson {
public static void main(String[] args){
Person p1 = new Person();
System.out.println(p1.getName());
System.out.println(p1.getAge());
}
}

五、完整示例:封装的实践
Student.java
// 学生类(封装属性,提供getter/setter)
public class Student {
// 私有属性
private String id; // 学号
private String name; // 姓名
private double score; // 成绩(0-100)
// 无参构造
public Student() {}
// 有参构造
public Student(String id, String name, double score) {
this.id = id;
this.name = name;
this.setScore(score); // 调用setter,复用校验逻辑
}
// getter和setter
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
// 成绩校验:必须在0-100之间
if (score < 0 || score > 100) {
System.out.println("成绩不合法!默认设置为0");
this.score = 0;
} else {
this.score = score;
}
}
// 打印学生信息
public void showInfo() {
System.out.println("学号:" + id + ",姓名:" + name + ",成绩:" + score);
}
}
// 测试类
public class TestStudent {
public static void main(String[] args) {
Student stu1 = new Student();
stu1.setId("S001");
stu1.setName("张三");
stu1.setScore(95);
stu1.showInfo(); // 学号:S001,姓名:张三,成绩:95.0
Student stu2 = new Student("S002", "李四", 150); // 成绩不合法!默认设置为0
stu2.showInfo(); // 学号:S002,姓名:李四,成绩:0.0
}
}
TestStudent.java
package study_7_4;
public class TestStudent {
public static void main(String[] args){
Student stu1 = new Student();
stu1.setId("S001");
stu1.setName("张三");
stu1.setScore(95);
stu1.showInfo();
Student stu2 = new Student("S002","李四",100);
stu2.showInfo();
}
}

六、练习
封装练习:定义一个 “图书类(Book)”,包含属性(图书编号)、
bookId(书名)、
title(价格,必须≥0)。用
price修饰属性,提供
private(
getter/setter需校验价格≥0,否则默认 0),并添加构造方法和
setPrice方法(打印图书信息)。
showInfo
this 练习:在上面的 Book 类中,确保构造方法和中使用
setter关键字区分属性和参数。
this
今日总结
封装的核心是 “隐藏内部细节,暴露公共接口”,通过隐藏属性,
private控制访问。访问修饰符控制访问范围:
getter/setter(仅本类)、默认(同包)、
private(同包 + 子类)、
protected(全局)。
public关键字代表当前对象,用于区分属性和参数,或调用本类其他构造方法。
this
其他:
Java 中构造方法的两种赋值逻辑:this 直接赋值与 setter 方法调用的区别与应用场景-CSDN博客



