📌 目录
1. 什么是封装?
封装(Encapsulation) 是面向对象编程中的一个基本特性,指将对象的状态(属性)和行为(方法)捆绑在一起,并通过对外提供的接口来访问对象的状态,从而隐藏对象的实现细节。封装有助于保护对象的内部状态,防止外部直接访问和修改。
封装的核心思想是将类的内部实现和外部暴露的接口分离,使得对象的内部实现对外部不可见,只能通过特定的访问方法进行操作。
2. 封装的特点
- 数据隐藏:通过访问修饰符控制属性和方法的可见性,使得外部无法直接访问对象的内部状态。
- 保护数据:通过封装,可以有效控制对数据的访问,防止外部修改对象的状态。
- 接口暴露:通过 getter 和 setter 方法暴露对象的状态,使外部可以通过这些方法来访问或修改对象的属性。
- 增强灵活性:通过修改 getter 和 setter 方法的实现,而不影响外部调用,增强了代码的灵活性。
3. 封装的实现
3.1 使用访问修饰符
在 Java 中,通过访问修饰符来控制类、属性和方法的访问权限。常用的访问修饰符有:
- public:公有,任何地方都可以访问。
- private:私有,只有类内部可以访问。
- protected:受保护,子类和同一包中的类可以访问。
- 默认(不写修饰符):包内可见,同一包中的类可以访问。
通过将类的属性设置为 private
,外部无法直接访问,只有通过公共的 getter 和 setter 方法才能访问和修改。
3.2 提供getter和setter方法
通常,封装类中的属性会设置为 private
,并通过 public
的 getter 和 setter 方法来提供对属性的访问。
- getter 方法用于获取属性值。
- setter 方法用于设置属性值。
public class Person {
// 将属性设置为私有,无法直接访问
private String name;
private int age;
// 获取 name 的 getter 方法
public String getName() {
return name;
}
// 设置 name 的 setter 方法
public void setName(String name) {
this.name = name;
}
// 获取 age 的 getter 方法
public int getAge() {
return age;
}
// 设置 age 的 setter 方法
public void setAge(int age) {
if (age >= 0) { // 设置年龄时进行合法性检查
this.age = age;
} else {
System.out.println("年龄不能为负数");
}
}
}
通过这种方式,外部可以使用 getter 和 setter 方法访问和修改 name
和 age
属性,而不能直接访问它们。通过 setter 方法,可以加入额外的逻辑(如合法性检查)。
4. 封装的优势
- 数据保护:封装可以防止外部直接访问对象的内部数据,防止数据被非法修改。
- 提高灵活性和可维护性:修改内部实现不会影响到外部调用者,只要 getter 和 setter 方法不变,外部代码就不会受到影响。
- 控制属性访问:可以在 setter 方法中增加额外的验证,确保数据的有效性和合法性。
- 增强可重用性:封装使得类的功能更独立,可以更容易地重用。
5. 封装的应用场景
- 安全性要求高的应用:封装保护敏感数据(如银行账户信息),防止外部未经授权的访问。
- 用户输入验证:通过 setter 方法验证输入数据的合法性,如年龄不允许为负数、用户名不为空等。
- 动态修改内部实现:封装允许你在不改变外部接口的情况下修改类的内部实现,提高代码的灵活性和可维护性。
- 大型软件项目:通过封装可以分离数据和操作,减少代码之间的耦合,提高代码模块化程度。
6. 封装的实例化
封装类的实例化与普通类一样,可以通过构造方法或 setter 方法为对象的属性赋值。在外部代码中,通过调用 getter 和 setter 方法来访问和修改对象的状态。
public class TestEncapsulation {
public static void main(String[] args) {
// 创建 Person 类的对象
Person person = new Person();
// 使用 setter 方法设置属性
person.setName("John");
person.setAge(30);
// 使用 getter 方法获取属性
System.out.println("Name: " + person.getName());
System.out.println("Age: " + person.getAge());
}
}
输出:
Name: John
Age: 30
7. 封装的示例代码
示例 1:封装实现
public class Student {
// 私有字段,不能直接访问
private String name;
private int grade;
// 构造方法
public Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
// 获取学生姓名
public String getName() {
return name;
}
// 设置学生姓名
public void setName(String name) {
this.name = name;
}
// 获取学生成绩
public int getGrade() {
return grade;
}
// 设置学生成绩
public void setGrade(int grade) {
if (grade >= 0 && grade <= 100) {
this.grade = grade;
} else {
System.out.println("成绩必须在 0 到 100 之间");
}
}
// 显示学生信息
public void displayInfo() {
System.out.println("学生姓名: " + getName());
System.out.println("学生成绩: " + getGrade());
}
}
public class TestStudent {
public static void main(String[] args) {
Student student = new Student("Alice", 95);
student.displayInfo();
// 尝试设置无效成绩
student.setGrade(110); // 输出:成绩必须在 0 到 100 之间
student.setGrade(85);
student.displayInfo(); // 更新后输出学生信息
}
}
输出:
学生姓名: Alice
学生成绩: 95
成绩必须在 0 到 100 之间
学生姓名: Alice
学生成绩: 85
发表回复