构造对象时对对象的最终引用

时间:2015-05-19 09:10:54

标签: java

假设我有一些类的引用,它是最终的:

public final Mycalss ref;

和MyClass有几个属性(不是最终属性)。现在,当我像这样构造MyClass对象时:

ref = new MyClass( some arguments);

这是否意味着其他线程可以安全地查看Myclass的内容,因为它是最终引用的?

4 个答案:

答案 0 :(得分:4)

创建引用final意味着一旦将对象分配给该引用,就不能将其他对象分配给该引用。

但即使引用声明为final,您也可以更改同一对象的值。

喜欢:

public final Myclass ref;
ref = new Myclass();

//this is not allowed
ref = new MyClass();   //since you have already assigned an object to your final reference

//this is allowed
ref.setSomeProperty("abc"):

有关线程和最终的答案,请参阅@Erwin Bolwidt的答案。

答案 1 :(得分:2)

来自Java Language Specification section 17.5

  

最终字段的使用模型很简单:设置最终字段   对于该对象的构造函数中的对象;并且不要写   引用正在另一个地方构建的对象   线程可以在对象的构造函数完成之前看到它。如果这   跟随,然后当另一个线程看到该对象时,那   线程将始终看到正确构造的版本   对象的最终字段。它还会看到任何对象的版本或   由最终字段引用的数组,这些字段至少是最新的   最后的字段是。

(我的重点补充)

这是JLS的“线程和锁定”部分17的一部分,其中Java Memory Model规范也是其中的一部分。

是的,你是对的。这是安全构建对象的正确方法。

答案 2 :(得分:1)

正如其他人所说final意味着只能对此变量进行一次分配。但是,在多线程环境中,如果线程A在线程B发出assignemnt之前访问该对象,则线程A将看到null。这意味着线程A可以看到变量的两个不同值。

此外,您应该记住Memory Consistency Errors - 即,一个线程对对象所做的更改可能对另一个线程不可见。我建议您阅读同步和volatile关键字 - this is a good place to start

答案 3 :(得分:0)

如果你想让所有类都看到一个类的实例,其属性是不可变的,你应该将属性声明为private,而不是创建任何setter,并使用Singleton模式(你可以在google上找到它,基本上你的类的构造函数是私有的,在你的类中你有一个静态的字段并且是你的类的唯一实例,你创建一个静态的getInstance()方法并返回当前实例和/或实例化它它是空的。

该课程将如下所示:

public class A {
   private static A instance;

   private A() {}

   public static synchronized A getInstance() {
      if (instance == null) {
         instance = new A();
      }
      return instance;
   }
}