java - 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");
你能给我解释一下吗?
解决方案
初始化顺序始终如下:
- 递归初始化超类(与所讨论的示例无关,因为它没有超类)
- 静态字段和静态初始化器
- 实例字段和实例初始化器
- 构造函数
因此,您的示例中的初始化顺序将是:
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
推荐阅读
- python - Celery EncodeError(TypeError('响应类型的对象不是 JSON 可序列化的'))
- ios - 选择器“getExportedModule”没有已知的类方法
- c# - 使用 LINQ 查询检查特定值是否在表中出现多次
- json-path-expression - 在单个 JsonPath 语法过滤器中提取文字和嵌套的 Json 对象值
- inheritance - Solidity 继承覆盖公共常量
- javascript - 避免嵌套 Observables(完成时的 mergeMap)
- performance - 如何强制TensorFlow同时使用同一个GPU的所有计算部分?
- html - 悬停令人不安
- deployment - Vercel:为每个域动态变化的项目文件?
- python - 如何使用 python Turtle 包绘制虚线圆