为了账号安全,请及时绑定邮箱和手机立即绑定

为什么静态字段没有及时初始化?

为什么静态字段没有及时初始化?

MM们 2019-11-27 11:18:41
以下代码仅打印null一次。class MyClass {   private static MyClass myClass = new MyClass();   private static final Object obj = new Object();   public MyClass() {      System.out.println(obj);   }   public static void main(String[] args) {}}为什么在构造函数运行之前不初始化静态对象?更新资料我只是在没有注意的情况下复制了这个示例程序,我以为我们在谈论2个Object字段,现在我看到第一个是MyClass字段..:/
查看完整描述

3 回答

?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

因为静态元素是按照在源代码中给出的顺序进行初始化的。


看一下这个:


class MyClass {

  private static MyClass myClass = new MyClass();

  private static MyClass myClass2 = new MyClass();

  public MyClass() {

    System.out.println(myClass);

    System.out.println(myClass2);

  }

}

那将打印:


null

null

myClassObject

null

编辑


好吧,让我们更清楚一点。


静态函数按照源代码中声明的顺序一一初始化。

由于第一个静态字段在其余字段之前进行了初始化,因此在其初始化期间,其余静态字段为null或默认值。

在第二个静态变量的初始化期间,第一个静态变量是正确的,但其余的仍为null或默认值。

明白了吗?


编辑2


正如Varman指出的那样,在初始化时对其自身的引用将为null。如果考虑一下,这是有道理的


查看完整回答
反对 回复 2019-11-27
?
万千封印

TA贡献1891条经验 获得超3个赞

让我们尝试另一种方式来解释这一点...

这是您首次引用该类时JVM经历的顺序MyClass

  1. 将字节码加载到内存中。

  2. 清除了用于静态存储的内存(二进制零)。

  3. 初始化类:

    1. 按照显示顺序执行每个静态初始化程序,其中包括静态变量和static { ... }块。

    2. 然后,JVM将您的myClass静态变量初始化为的新实例MyClass

    3. 发生这种情况时,JVM会注意到MyClass已加载(字节码)并且正在初始化,因此它会跳过初始化。

    4. 在堆上为对象分配内存。

    5. 执行构造函数。

    6. 打印出obj仍然是静态的值null(因为它不是堆和构造函数初始化变量的一部分)。

    7. 构造函数完成后,执行下一个静态初始值设定项obj,将其设置为的新实例Object

  4. 类初始化完成。从这一点来看,所有构造函数调用都将按照您的假定/期望的方式运行-这obj将不仅仅是nullObject实例的引用。

请记住,Java指定给final变量分配一次值。并不是确保在代码引用它时为它分配一个值,除非您确保在赋值后代码引用了它。

这不是错误。这是在类自身初始化期间处理类使用的已定义方法。如果不是这样,那么JVM将陷入无限循环。请参阅步骤#3.3(如果JVM不跳过正在初始化过程中的类的初始化,它将继续对其进行初始化-无限循环)。

还要注意,这一切都发生在首先引用该类的同一线程上。其次,JVM保证初始化将在允许任何其他线程使用此类之前完成。


查看完整回答
反对 回复 2019-11-27
?
HUWWW

TA贡献1874条经验 获得超12个赞

这是因为Java按照声明的顺序执行静态部分。在您的情况下,顺序为


新的MyClass

新对象

执行#1时,obj仍未初始化,因此它输出null。尝试以下操作,您将看到区别:


class MyClass {

  private static final Object obj = new Object();

  private static MyClass myClass = new MyClass();

  public MyClass() {

    System.out.println(obj); // will print null once

  }

}

一般来说,最好避免一起使用这种构造。如果您尝试创建一个单例,那么该代码片段应如下所示:


class MyClass {


  private static final MyClass myClass = new MyClass();


  private Object obj = new Object();


  private MyClass() {

    System.out.println(obj); // will print null once

  }

}


查看完整回答
反对 回复 2019-11-27
  • 3 回答
  • 0 关注
  • 439 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信