如何在Java中创建具有可变对象引用的不可变类?
不可变的对象是那些状态一旦初始化就不能更改的对象。有时有必要根据要求创建一个不可变的类。例如,所有原始包装器类(Integer,Byte,Long,Float,Double,Character,Boolean和Short)在Java中都是不可变的。字符串类也是一个不变的类。
要创建自定义不可变类,我们必须执行以下步骤
将课程声明为最终课程,因此无法扩展。
将所有 字段设为私有,以便不允许直接访问。
不要为变量提供setter方法(修改字段的方法),这样就无法设置它。
将所有可变字段定为最终值,以便它们的值只能分配一次。
通过执行深度复制的构造函数初始化所有字段。
在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(); } } //地址.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