不变性的定义表明,在构造之后,对象的状态(其数据)不能被改变.
这里提出了一个问题,在我看来,对象包含的状态和数据是不同的东西.也许状态意味着通过getter提供的数据?
它并不意味着标记为私有且外部世界不可见的数据,这些数据确实可以改变而不会改变对象的状态.
告诉我这是否正确:
final class Obj1 {
private final int i;
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1(int i) {
this.i = i;
}
public getI() {
j = rnd.nextInt(1000);
return i;
}
}
Run Code Online (Sandbox Code Playgroud)
一个实例Obj1是一个不可变对象.
final class Obj2 {
private final int i;
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1(int i) {
this.i = i;
}
public getI() {
return i;
}
public getJ() {
return j;
}
}
Run Code Online (Sandbox Code Playgroud)
是Obj2一个可变或不可变对象的实例,为什么?如果每次调用getter时我们在getJ体中得到下一个Random怎么办?
这样的课程怎么样?可变/不可变,为什么?
final class Obj3 {
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1() {
}
public getJ() {
return j;
}
}
Run Code Online (Sandbox Code Playgroud)
这个如何?可变/不可变,为什么?
final class Obj4 {
private final Random rnd = new Random();
public Obj1() {
}
public getRnd() {
return rnd.nextInt(1000);
}
}
Run Code Online (Sandbox Code Playgroud)
关于不变性的一个重要观点是,对象的可观察状态不得改变.
一个非常好的例子java.lang.String,它经常被引用为不可变类的规范示例.它有一个非final字段,即hash.hash保存哈希码,但默认为0.在第一次hashCode()调用并在该字段中缓存时,懒惰地计算哈希码.这样,对象的内部状态String可以改变,但是可观察状态永远不会改变(因为hashCode()总是返回相同的值,无论是计算还是仅返回缓存的值).
这意味着,您所提供的前三个样本(Obj1,Obj2,Obj3)是不可改变的:他们没有制定者并没有别的可以改变施工后通过他们的方法的返回值(这将是宣布领域是个好主意final,但它不是一个不可变性的要求).另请注意,您也可以Random完全在这些类中省略该字段,因为它在构建之后仍未使用.
我会说最后一个样本(Obj4)肯定是可变的,因为getRnd()每次从中读取时(即每次调用时)都会更改状态(即下一个调用返回的内容getRnd()).
因此,回答标题中的问题:是的,如果对象的状态在类本身的状态下是不可观察的,则引用Random对象的类可以是不可变的Random.