Java 类的 Linking 和 Initializing 简单笔记

简介: Java 类的 Linking 和 Initializing 简单笔记

       Java 类的生命周期分为 5 个阶段,分别是 Loading(加载)、Linking(连接)、Initializing(初始化)、Using(使用) 和 Unloading(卸载)。其中 Linking 阶段又分为 Verification(验证)、Preparation(准备) 和 Resolution(解析) 三个部分。

       大致情况如下图所示。

11111.png

       一般所说的类加载指的是 Loading、Linking 和 Initializing 这几个阶段。其中,Loading 主要讨论关于 双亲委派、懒加载、自定义类加载器等相关的知识。在 Linking 的 Preparation 阶段 和 Initializing 可以了解类静态成员变量的初始化。在学习 Java 的相关基础知识时,了解内部的工作机制,要比单纯记忆相关语法规则可能更容易理解。这里,通过一个简单的代码实例来了解一下在 Preparation 阶段和 Initializing 阶段的对类中静态变量的赋初始值与初始化的过程。


一、一段没有意义的代码

       下面的代码是一段没有意义的代码,项目中也不会有如此的写法,但是通过下面的代码能够很好的解释静态变量在每个阶段时的值。

publicclassLinking {
publicstaticvoidmain(String[] args) {
System.out.println(Test.count);
    }
}
classTest {
publicstaticintcount=2;
publicstaticTesttest=newTest();
privateTest() {
count++;
    }
}

       上面的代码,主要用来输出 Test 类中的 count 静态变量的值。从 Test 类中可以看到,定义了静态的 int 型变量 count 和 静态的 Test 类对象。在 main 中输出时,Test.count 的值是多少。这里通过编译并运行代码来进行查看结果。

22222.png

       在 IDEA 中的输出结果是 3。对于这个结果,能够了解在整个类加载时 Preparation 阶段和 Initializing 阶段 时的所作所为,即可了解该值为何如此输出。


二、Linking 阶段和 Initializing 阶段的所作所为

       在类加载的 Linking 阶段中,主要完成了三个步骤,分别是 Verification、Preparation 和 Resolution。其中,Verification 是用来验证 class 文件是否符合 JVM 的规范,比如文件格式校验、元数据校验、字节码校验 和 符号引用校验。在类验证通过后是 Preparation,该步骤主要为类中定义的静态成员变量分配内存,并为静态成员变量赋默认值。Resolution 用来完成符号引用到直接引用的解析,可以理解为将 class 文件的常量池的各种符号引用解析为内存地址的指针引用。

       Initializing 阶段用来完成类的初始化代码,其中包含静态成员变量的初始化。


三、解释代码

       有了上面两个阶段大体的工作内容,再来看一下代码。在代码中,定义了一个 Test 类,类中定义了两个静态的成员变量,分别是 int 型和 Test 类。在 Preparation 阶段,会为这两个静态成员变量分配空间,赋默认值。那么此时为 count 静态变量赋默认值,int 类型的默认值为 0,那么 count 的值为 0;类对象的默认值为 null,那么 test 的值为 null。在 Initializing 阶段,count 的值根据代码被初始化为 2,test 在经过构造方法的执行后,count 的值进行了自增 1 的操作,由 2 变为了 3。因此,在 main 方法中,输出 Test.count 时,它的值为 3。


四、修改代码

       修改上面的代码,调整两个静态成员变量定义的顺序,再来观察它的输出结果,代码如下:

classTest {
publicstaticTesttest=newTest();
publicstaticintcount=2;
privateTest() {
count++;
    }
}

       接着按照上面的方式进行分析。首先,在 Preparation 阶段,test 的默认值为 null,count 的默认值为 0。接着,在 Initializing 阶段,调用 Test 的构造方法,此时 count 经过自增 1 变为了 1,再来完成 count = 2 的初始化。最后在 main 方法中输出 Test.count 时,它的值为 2。输出结果如下:

33333.png

五、总结

       上面的内容中,介绍了 Java 类在加载时的部分内容,也从例子代码对其机制有了简单的了解。很多时候,语法规则细节之类的并不是能特别好的记住,有些知识也并不是完全靠记就好使的,更多的是了解技术背后的一些原理,这样对知识的掌握才能更加深刻。

相关文章
|
8天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
17天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
39 8
|
1月前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
51 17
|
26天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
86 4
|
1月前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
49 2
|
1月前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
1月前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
41 4
|
1月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
1月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编