Java - 封装(Encapsulation)

更新于 2025-12-27

封装是面向对象编程(OOP)的四大基本概念之一。其余三个分别是:继承(Inheritance)多态(Polymorphism)抽象(Abstraction)

在 Java 中,封装是一种将数据(变量)和操作数据的代码(方法)捆绑成一个单一单元的机制。通过封装,类中的变量对外部类是隐藏的,只能通过当前类的方法进行访问。因此,封装也被称为数据隐藏

在 Java 中实现封装的方法:

  1. 将类的变量声明为 private
  2. 提供公共的 setter 和 getter 方法,用于修改和查看变量的值。

Java 封装示例

以下是一个演示如何在 Java 中实现封装的示例:

/* 文件名:EncapTest.java */
public class EncapTest {
   private String name;
   private String idNum;
   private int age;

   public int getAge() {
      return age;
   }

   public String getName() {
      return name;
   }

   public String getIdNum() {
      return idNum;
   }

   public void setAge(int newAge) {
      age = newAge;
   }

   public void setName(String newName) {
      name = newName;
   }

   public void setIdNum(String newId) {
      idNum = newId;
   }
}

上述 EncapTest 类中的公共 setXXX()getXXX() 方法是实例变量的访问入口。通常这些方法被称为 gettersetter。因此,任何想要访问这些变量的类都必须通过这些 getter 和 setter 方法。

可以使用以下程序访问 EncapTest 类的变量:

/* 文件名:RunEncap.java */
public class RunEncap {
   public static void main(String args[]) {
      EncapTest encap = new EncapTest();
      encap.setName("James");
      encap.setAge(20);
      encap.setIdNum("12343ms");

      System.out.print("Name : " + encap.getName() + 
                       " Age : " + encap.getAge());
   }
}

输出结果:

Name : James Age : 20

封装的好处

  • 类的字段可以设置为只读只写
  • 类可以完全控制其字段中存储的内容。

Java 封装:只读类(Read-Only Class)

只读类仅包含 getter 方法用于获取属性值,不应包含任何 setter 方法。

示例:创建只读类

// 类 "Person"
class Person {
   private String name = "Robert";
   private int age = 21;

   // Getter 方法
   public String getName() {
      return this.name;
   }

   public int getAge() {
      return this.age;
   }
}

public class Main {
   public static void main(String args[]) {
      // 创建 Person 类的对象
      Person per = new Person();

      // 获取并打印值
      System.out.println("Name of the person is: " + per.getName());
      System.out.println("Age of the person is: " + per.getAge());
   }
}

输出:

Name of the person is: Robert
Age of the person is: 21

Java 封装:只写类(Write-Only Class)

只写类仅包含 setter 方法用于设置属性值,不应包含任何 getter 方法。

示例:创建只写类

// 类 "Person"
class Person {
   private String name;
   private int age;

   // Setter 方法
   public void setName(String name) {
      this.name = name;
   }

   public void setAge(int age) {
      this.age = age;
   }
}

public class Main {
   public static void main(String args[]) {
      // 创建 Person 类的对象
      Person per = new Person();

      // 设置值
      per.setName("Robert");
      per.setAge(21);
   }
}

Java 封装:更多示例

示例 1:Person 类(完全封装)

// 类 "Person"
class Person {
   private String name;
   private int age;

   // Setter 方法
   public void setName(String name) {
      this.name = name;
   }

   public void setAge(int age) {
      this.age = age;
   }

   // Getter 方法
   public String getName() {
      return this.name;
   }

   public int getAge() {
      return this.age;
   }
}

// 测试封装类 "Person" 的主类
public class Main {
   public static void main(String args[]) {
      Person per1 = new Person();
      Person per2 = new Person();

      // 设置值
      per1.setName("Robert");
      per1.setAge(21);
      per2.setName("Riyan");
      per2.setAge(22);

      // 打印值
      System.out.println("Person 1: Name : " + per1.getName() + " Age : " + per1.getAge());
      System.out.println("Person 2: Name : " + per2.getName() + " Age : " + per2.getAge());
   }
}

输出:

Person 1: Name : Robert Age : 21
Person 2: Name : Riyan Age : 22

示例 2:Employee 类(完全封装)

// 类 "Employee"
class Employee {
   private String emp_name;
   private String emp_id;
   private double net_salary;

   // 构造函数
   public Employee(String emp_name, String emp_id, double net_salary) {
      this.emp_name = emp_name;
      this.emp_id = emp_id;
      this.net_salary = net_salary;
   }

   // Getter 方法
   public String getEmpName() {
      return emp_name;
   }

   public String getEmpId() {
      return emp_id;
   }

   public double getSalary() {
      return net_salary;
   }

   // Setter 方法
   public void setEmpName(String emp_name) {
      this.emp_name = emp_name;
   }

   public void setEmpId(String emp_id) {
      this.emp_id = emp_id;
   }

   public void setSalary(double net_salary) {
      this.net_salary = net_salary;
   }
}

// 测试封装类 "Employee" 的主类
public class Main {
   public static void main(String args[]) {
      // 使用构造函数设置初始值
      Employee emp = new Employee("Robert", "EMP001", 75450.00);

      // 打印初始数据
      System.out.println("Employee (Initial Values):");
      System.out.println(emp.getEmpId() + " , " + emp.getEmpName() + " , " + emp.getSalary());

      // 使用 setter 方法更新值
      emp.setEmpName("Riyan");
      emp.setEmpId("EMP002");
      emp.setSalary(90500.00);

      // 打印更新后的数据
      System.out.println("Employee (Updated Values):");
      System.out.println(emp.getEmpId() + " , " + emp.getEmpName() + " , " + emp.getSalary());
   }
}

输出:

Employee (Initial Values):
EMP001 , Robert , 75450.0
Employee (Updated Values):
EMP002 , Riyan , 90500.0