代码之家  ›  专栏  ›  技术社区  ›  Student

分配的最终对象字段在构造函数中可能仍然为空,这是真的吗?

  •  5
  • Student  · 技术社区  · 16 年前

    分配的最终对象字段在构造函数中可能仍然为空,这是真的吗?

    class MyClass {
      private final Object obj = new Object();
      public MyClass() {
        System.out.println(obj); // may print null?
      }
    }
    

    如果是,这不是一个bug吗?

    5 回复  |  直到 14 年前
        1
  •  4
  •   ILMTitan    16 年前

    正如其他答案所讨论的,不,这是不可能发生的。但是,对于分配的最终静态字段,它可以。

    class MyClass {
      private static MyClass myClass = new MyClass();
      private static final Object obj = new Object();
      public MyClass() {
        System.out.println(obj); // will print null once
      }
    }
    
        2
  •  3
  •   Tendayi Mawushe    16 年前

    这是不可能的 initializers run before the constructor is invoked .

    变量初始值设定项 private final Object obj = new Object(); 在调用构造函数之前运行。这同样适用于静态或其他初始化块。

    使用初始值设定项时要注意的一点是 初始值设定项无法进行前向引用 编写初始值设定项时,不能引用在初始化变量后以文本方式声明的任何实例变量。

        3
  •  2
  •   danben    16 年前

    初始化器 Object obj = new Object(); 将在构造函数内的代码之前运行,因此 obj 不能 null .

    请注意,如果不初始化 OBJ 任何地方。

        4
  •  2
  •   Ben Lings    16 年前

    为我工作:

    $ cat MyClass.java
    class MyClass {
        private final Object obj = new Object();
        public MyClass() {
            System.out.println(obj); // may print null?
        }
        public static void main(String[] args) { new MyClass(); }
    }
    $javac MyClass.java; java MyClass
    java.lang.Object@19908ca1
    

    编译器将所有字段初始值设定项复制到所有构造函数的开头。

    但是,在Java 5内存模型下,如果 this 引用“escape”在构造函数结尾之前,其他线程可以看到未初始化的值 final 字段(可以看到 null 在这种情况下)。

        5
  •  2
  •   Simon Nickerson    16 年前

    有了像你这样的简单例子,就不会有什么不好的事情发生。然而,它 是 可能的 final 如果使用可疑的实践(如在构造函数中调用可重写的方法),则字段可视为未初始化。

    例如,以下程序打印“我最喜欢的颜色是空的”,即使它引用了最后的变量 favouriteColour ,设置为 "blue" 在构造函数中。

    abstract class SuperClass {
        final String favouriteColour;
    
        SuperClass() {
            announceFavouriteColour();
            favouriteColour = "blue";
        }
    
        abstract void announceFavouriteColour();
    }
    
    public class FinalTest extends SuperClass {
        void announceFavouriteColour() {
            System.out.println("My favourite colour is " + favouriteColour);
        }
    
        public static void main(String[] args) {
            new FinalTest();
        }
    }