如何在Java中创建包含可变对象引用的不可变类?\n


不可变对象是指其状态一旦初始化后就不能更改的对象。有时根据需要创建不可变类是必要的。例如,所有基本包装类(Integer、Byte、Long、Float、Double、Character、Boolean 和 Short)在 Java 中都是不可变的。String 类也是一个不可变类。

要创建自定义不可变类,我们需要执行以下步骤

  • 将类声明为final,以便它不能被扩展。
  • 将所有字段设为私有,以便不允许直接访问。
  • 不要为变量提供setter 方法(修改字段的方法),以便它不能被设置。
  • 将所有可变字段设为final,以便它们的值只能分配一次。
  • 通过执行深度复制的构造函数初始化所有字段。
  • 在 getter 方法中执行对象的克隆以返回副本,而不是返回实际的对象引用。
  • 如果实例字段包含对可变对象的引用,则不允许更改这些对象
  • 不要提供修改可变对象的方法。
  • 不要共享对可变对象的引用。切勿存储传递给构造函数的外部可变对象的引用。如有必要,创建副本并存储对副本的引用。类似地,在需要时创建我们内部可变对象的副本,以避免在我们的方法中返回原始对象。

示例

在线演示

// Employee.java
final class Employee {
   private final String empName;
   private final int age;
   private final Address address;
   public Employee(String name, int age, Address address) {
      super();
      this.empName = name;
      this.age = age;
      this.address = address;
   }
   public String getEmpName() {
      return empName;
   }
   public int getAge() {
      return age;
   }
   /* public Address getAddress() {
      return address;
      }
   */
   public Address getAddress() throws CloneNotSupportedException {
      return (Address) address.clone();
   }
}
// Address.java
class Address implements Cloneable {
   public String addressType;
   public String address;
   public String city;
   public Address(String addressType, String address, String city) {
      super();
      this.addressType = addressType;
      this.address = address;
      this.city = city;
   }
   public String getAddressType() {
      return addressType;
   }
   public void setAddressType(String addressType) {
      this.addressType = addressType;
   }
   public String getAddress() {
      return address;
   }
   public void setAddress(String address) {
      this.address = address;
   }
   public String getCity() {
      return city;
   }
   public void setCity(String city) {
      this.city = city;
   }
   public Object clone() throws CloneNotSupportedException {
      return super.clone();
   }

   @Override
   public String toString() {
      return "Address Type - "+addressType+", address - "+address+", city - "+city;
   }
}
// MainClass.java
public class MainClass {
   public static void main(String[] args) throws Exception {
      Employee emp = new Employee("Adithya", 34, new Address("Home", "Madhapur", "Hyderabad"));
      Address address = emp.getAddress();
      System.out.println(address);
      address.setAddress("Hi-tech City");
      address.setAddressType("Office");
      address.setCity("Hyderabad");
      System.out.println(emp.getAddress());
   }
}

在上面的示例中,我们将返回该实例的深度克隆副本,而不是返回原始的Address对象。地址类必须实现Cloneable接口。

输出

Address Type - Home, address - Madhapur, city - Hyderabad
Address Type - Home, address - Madhapur, city - Hyderabad

更新于: 2020年2月6日

11K+ 浏览量

开启你的职业生涯

通过完成课程获得认证

开始学习
广告

© . All rights reserved.