不可变类的配方

不可变对象是无法更改其状态的对象。不可变类是一个类,其实例在设计和实现方面是不可变的。最常见的不可变性示例 Java 类是 java.lang.String

以下是一个陈规定型的例子:

public final class Person {
    private final String name;
    private final String ssn;     // (SSN == social security number)

    public Person(String name, String ssn) {
        this.name = name;
        this.ssn = ssn;
    }

    public String getName() {
        return name;
    }
   
    public String getSSN() {
        return ssn;
    }
}

对此的一种变化是将构造函数声明为 private 并提供 public static 工厂方法。

不可变类的标准配方如下:

  • 必须在构造函数或工厂方法中设置所有属性。
  • 应该没有制定者。
  • 如果出于接口兼容性原因需要包含 setter,它们应该不执行任何操作或抛出异常。
  • 所有属性都应声明为 privatefinal
  • 对于引用可变类型的所有属性:
    • 应该使用通过构造函数传递的值的深层副本初始化该属性,并且
    • 属性的 getter 应该返回属性值的深层副本。
  • 该类应声明为 final,以防止有人创建不可变类的可变子类。

还有几点需要注意:

  • 不可变性不会阻止对象可以为空; 例如,null 可以分配给 String 变量。
  • 如果将不可变类属性声明为 final,则实例本身就是线程安全的。这使得不可变类成为实现多线程应用程序的良好构建块。