前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 类的 Linking 和 Initializing 简单笔记

Java 类的 Linking 和 Initializing 简单笔记

作者头像
码农UP2U
发布2021-12-10 08:51:28
3000
发布2021-12-10 08:51:28
举报
文章被收录于专栏:码农UP2U码农UP2U

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

大致情况如下图所示。

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

一、一段没有意义的代码

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

代码语言:javascript
复制
public class Linking {
    public static void main(String[] args) {
        System.out.println(Test.count);
    }
}

class Test {
    public static int count = 2;
    public static Test test = new Test();

    private Test() {
        count ++;
    }
}

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

在 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。

四、修改代码

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

代码语言:javascript
复制
class Test {
    public static Test test = new Test();
    public static int count = 2;

    private Test() {
        count ++;
    }
}

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

五、总结

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-12-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农UP2U 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档