正如堆纸器所说的那样,
final确保该类没有被子类化。这很重要,因此任何 依赖 其不变性的代码都可以安全地这样做。
例如,不可变类型(每个字段也是不可变类型)可以在线程之间自由使用,而不必担心数据争用等。现在考虑:
public class Person { private final String name; public Person(String name) { this.name = name; } public String getName() { return name; }}这 看起来 喜欢你可以分享
Person没有问题的自由跨线程的实例。但是,当您共享的对象 实际上是 一个可变子类时,该怎么办:
public class Employee extends Person { private String company; public Employee(String name, String company) { super(name); this.company = company; } public void setCompany(String company) { this.company = company; } public String getCompany() { return company; }}现在,
Employee不可以 在线程之间共享实例,因为它们不是不可变的。但是进行共享的代码 可能
只将它们作为
Person…的实例来了解,从而导致它们产生错误的安全感。
缓存也是如此-缓存和重用不可变类型应该是安全的,对吗?那么,它 是 安全的缓存实例那些真正不可变型的-但如果你正在处理一个类型本身不允许突变,但
不会 允许子类,它是突然不是安全了。
想一想
java.lang.Object。它没有任何可变字段,但是将每个
Object引用都视为对不变类型的引用显然是一个坏主意。基本上,这取决于您是否将不变性视为类型或对象的属性。真正不可变的类型声明“任何时候看到这种类型的引用,您都可以将其视为不可变的”
–而允许任意子类化的类型则不能声明该声明。
顺便说一句,有一个半途而废的方法:如果您可以将子类别限制为仅“受信任”的位置,则可以确保所有内容都是不可变的,但仍允许该子类别。Java中的访问使这一点变得棘手,但是例如在C#中,您可以有一个公共类,该公共类只允许在同一程序集中进行子类化-
提供一个在不可变性方面很好并且很强的公共API,同时仍然允许多态性的好处。



