这个类是不可变的吗?
下面的类没有final关键字,但它的成员变量是privateandfinal并且该类没有公开 mutate/set 方法。这个类是不可变的吗?
public class Abc {
private final int id;
private final String name;
public Abc(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
回答
类本身是不可变的,是的 - 如果您创建 justAbc的实例,则在创建实例后无法更改任何方面。
然而,这并不意味着任何接收类型参数的代码Abc都可以假定它是不可变的,并且具有所有优点......因为类不是final. 这是完全有可能的类型的对象兼容与Abc是可变的:
public class Mutable extends Abc {
private String value;
public Mutable(int id, String name) {
super(id, name);
}
public void setValue(String value) {
this.value = value;
}
@Override public String toString() {
return value;
}
}
现在假设您有处理 的代码Abc:
public class AbcConsumer {
private final Abc abc;
public AbcConsumer(Abc abc) {
this.abc = abc;
}
// No need to create a defensive copy or anything like that...
// abc is immutable, right?
public Abc getAbc() {
return abc;
}
}
在这里,消费者假设可以将其Abc视为不可变类来处理- 但是如果有人AbcConsumer通过传入Mutable实例而不是“普通”Abc实例来创建一个,则可能会导致问题。
这就是为什么当您创建一个不可变类型来实现它时通常是一个好主意final- 这样任何消费者都知道如果他们收到该类型的引用,它绝对是不可变的。
换句话说:是的,Abc该类是不可变的……但是您不能假设具有编译时类型的Abc引用是指不可变对象。
回答
正如所介绍的,是的,该类是不可变的。
类声明上的“final”关键字阻止它被扩展——它与不变性无关(除非你的变量被声明为 public 或 protected)。
编辑; “不相关”是一个糟糕的词选择,请参阅下面Jon Skeet 的回答
回答
不,很可能不是。
一个问题是术语。你说的课是什么意思?如果你的意思是这段代码,当然,它是不可变的。但是“这段代码”并不是与不变性概念特别相关的东西。如果我们考虑一下,这通常更有意义:这种类型。
比如,类型是 Abc不可变的吗?
如,给定:
public void foo(Abc abc) { ... }
假设收到的abc不可能改变是否安全?
然后答案是否定的。这是不安全的假设:类型Abc是mutable。
原因是有人可以做到这一点:
class SneakyAbc extends Abc {
private int id;
public void setId(int id) {
this.id = id;
}
public String getId() {
return id;
}
}
这就是为什么几乎总是制作不可变类的原因final,以完全保证它。
取决于你想用“这个术语是什么意思”的画笔画的花哨,如果Abc 的所有方法都是final,如果你真的想,你也可以认为它是不可变的:虽然类不需要是不可变的(子类可以添加一个新的非最终字段并为此创建 getter 和 setter),假设您不使用反射,您可以从 Abc 类型“见证”的所有内容确实看起来不可变。
究竟什么是不可变的定义,你需要进一步深入研究的知识。
请注意,像这样的东西java.io.File只有 final 字段并且是 final 的,但是,它具有可以修改的易于观察的状态:只需..删除文件,瞧您就可以看到它。您可以使用 和 拉类似的特技IdentityHashMap来创建一个人造但非常可观察的“场”。
因此,“不可变”作为一个概念:有用。作为授予某种类型或某些 Java 源文件的布尔标志:无用。