首页 > 解决方案 > JVM 执行代码以构建对象的顺序

问题描述

我正在学习 Oracle 的 OCA 8 认证。在我的研究中,我遇到了一个问题,它让我对 Java 对象的初始化顺序(静态块、构造函数、变量的初始化……)产生了一些疑问。问题如下:

public class InitTest{
   static String s1 = sM1("a");{
      s1 = sM1("b");
   }
   static{
      s1 = sM1("c");
   }
   public static void main(String args[]){
      InitTest it = new InitTest();
   }
   private static String sM1(String s){
      System.out.println(s);  return s;
   }
}

我的问题是对象每个部分的启动顺序:

1) {...}

2)静态{...}

3)初始化测试 {...}

4)静态字符串 s1 = sM1("a");

你能给我解释一下吗?

标签: java

解决方案


初始化顺序始终如下

  1. 递归初始化超类(与所讨论的示例无关,因为它没有超类)
  2. 静态字段和静态初始化器
  3. 实例字段和实例初始化器
  4. 构造函数

因此,您的示例中的初始化顺序将是:

1)静态字符串 s1 = sM1("a") ; - 静态初始化块和静态字段成员首先被处理,这发生在类加载器加载类之后(在你开始使用类或创建对象之前)。如果有更多的初始化程序或静态成员声明,​​则按照编写顺序执行。这就是为什么这个静态字段会在静态初始化块之前被初始化。

2) static {...} - 在第 1 点中解释。静态初始化器出现在静态变量s1的声明之前,这就是它按此顺序处理的原因(两者具有相同的优先级,但这里类内部的顺序获胜如果两者具有相同的优先级)。

3) {...} - 在静态初始化器和静态字段之后,实例初始化器和实例字段被初始化,所以实例初始化器在静态初始化器和静态字段s1之后。它们是使用构造函数创建新对象时首先被处理的,这发生在构造函数实际执行之前。

4.) InitTest {...} - 在初始化其他所有内容(所有初始化块和字段初始化)后调用构造函数。

有关类和对象初始化顺序的更多详细信息,您可以在 Java 语言规范中找到:https ://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.1 ,https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.2,https://docs.oracle.com/javase/specs/jls/se11/ _ _ html/jls-12.html#jls-12.5


推荐阅读