对象从最终字段可传递到达意味着什么?

时间:2014-08-20 06:07:03

标签: java immutability

This post讨论了可从最终字段传递的不可变对象:

  

不变性并不代表"不会改变"在Java中。这意味着"可以从最终字段传递到达,自最终字段设置以来没有改变,并且对包含最终字段的对象的引用没有逃脱构造函数"。

对于以下代码,

public class A() {
    private String myString;
    public A(String myString){
        this.myString = myString;
    }
    public String getMyStringAndYours(){
        return myString.concat("yours");
    }
}

是可以从最终字段传递的实例吗? 我想是因为:
1。 myString.valuefinal
2。 myString可以myString.value到达a
3。 A a.myString的实例可以从a

到达

附带问题:{{1}}是不可变的吗?

3 个答案:

答案 0 :(得分:5)

我暂时搁置可传递的,并专注于finalimmutability之间的区别。

class MyObject {
int a;
void setA(int val){
a=val;
}
}

final MyObject obj = new MyObject(); 

现在,由于obj 引用final,如果您尝试

,则会出现编译错误
obj = new MyObject(); // you can't re-initialize a final reference.

但你能做什么:

obj.setA(5); // perfectly valid.

您可以更改obj引用的对象的状态,但无法将obj重新初始化为其他对象

现在,如果MyObject内的所有字段都是final且所有设置者都是私有(或缺席),那么将无法做到

obj.setA(5); 

immutable对象是其内部状态无法更改的对象。

现在,回到可传递的。如果由对象B和反过来对象B组成的对象A具有对象C(组合)。您的对象A不是真正的不可变,除非所有可传递的对象都是不可变的 final ,即abc here a,{ {1}}和b应该是最终的,以防止重新分配对另一个对象的引用。此外,您应确保在创建时不共享c(避开A的范围)。如果它是共享的,那么任何其他对象都可以改变它。

编辑:

字符串不可变所以,你只需要将它们设为 final ,这样它们的封闭类就是 immutable

答案 1 :(得分:1)

A"足够不可变"。因为在构造之后,字段myString无法更改(至少在代码提供的上下文中),A的状态不会更改,从而使其不可变。

此外,String#concat(String)不会更改String的状态,如文档中所指定的,它会创建一个新的String,确保String是不可变的,并保持A不可变的。

答案 2 :(得分:1)

您具有相反顺序的可达性。考虑这些类:

public class SomeBean {
    private String a;
}

public class SomeOtherBean {
    private SomeBean someBean;
    ...
}

public class Foo {
    private final SomeOtherBean someOtherBean;
    private /* non-final */ SomeOtherBean someOtherBean2;
}

然后Foo.someOtherBean.someBeanFoo.someOtherBean.someBean.a可以从最终字段传递,因为Foo.someOtherBean是最终字段,而Foo.someOtherBean,您可以Foo.someOtherBean.someBeanFoo.someOtherBean.someBean.a {1}} 按照参考资料

另一方面,Foo.someOtherBean2.someBeanFoo.someOtherBean2.someBean.a 可以从最终字段传递,因为Foo.someOtherBean不是最终字段。