为什么最终关键字对于不可变类是必需的?
您能否澄清一下,为什么当我们将其设置为不可变关键字时,在class之前需要最终关键字。我的意思是,如果我们声明它的所有属性都是私有的和最终的,那么它也是一个不可变的类,不是吗?
抱歉,如果这个问题看起来很容易,但我真的对此感到困惑。帮帮我。
已编辑:我知道声明为 final 的类不能被子类化。但是,如果每个属性都是私有的和最终的,那么这有什么区别呢?
您能否澄清一下,为什么当我们将其设置为不可变关键字时,在class之前需要最终关键字。我的意思是,如果我们声明它的所有属性都是私有的和最终的,那么它也是一个不可变的类,不是吗?
抱歉,如果这个问题看起来很容易,但我真的对此感到困惑。帮帮我。
已编辑:我知道声明为 final 的类不能被子类化。但是,如果每个属性都是私有的和最终的,那么这有什么区别呢?
正如 stacker 所说,确保类没有被子类化。这很重要,这样任何依赖于其不变性的代码都可以安全地做到这一点。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,同时仍然允许多态性的好处。
不能对声明为 final 的类进行子类化。另请参见 http://docs.oracle.com/javase/tutorial/java/IandI/final.html
最终关键字的所有用法的不同语义在 Java 语言规范中进行了描述