• Java类的加载的一个小问题


    前言

    之前写了一篇文章专门介绍了一下类的加载和对象的创建流程,然后收到了一个博友的疑问,觉得蛮好的,在这里和大家分享下。

    博文地址:【Java基础】Java类的加载和对象创建流程的分析

    疑问

    类在加载的时候,是不是就可以被实例化?

     1 public class Test3 {
     2     public static Test3 t = new Test3();
     3 
     4     {
     5         System.out.println("blockA");
     6     }
     7 
     8     static {
     9         System.out.println("blockB");
    10     }
    11 
    12     public static void main(String[] args) {
    13         Test3 t1 = new Test3();
    14     }
    15 }

    运行结果

    1 blockA
    2 blockB
    3 blockA

    你对结果有疑问吗?和你认为的一样吗?

    分析

    其实这个问题如果理解了类的加载和对象的创建流程,其实很容易理解的。

    类的加载

    简单的流程是:

    1. 先加载静态内容:静态成员变量,静态代码块,静态方法。(按代码书写顺序加载)

    • 静态成员变量默认初始化,完成之后,静态成员变量显示初始化。
    • 执行静态的代码块内容。先执行父类的静态代码块,再执行子类的静态代码块。

    2. 静态内容加载完成之后,再加载非静态内容。

    3. 所有的静态内容和非静态内容加载完成之后,类加载完成。

    4. 类加载完成之后可以执行程序中具体的对象创建和代码。

    对象的创建

    1.给对象分配内存空间,其实就是分配内存地址。

    2.对类中的的非静态的成员变量开始默认初始化。

    3.加载对应的构造方法,执行隐式三步

    ①有个隐式的super(); 
    
    ②显示初始化(给所有的非静态的成员变量)
    
    ③执行非静态构造代码块
    
    之后才开始执行本类的构造方法中的代码

    4.对象创建完成

    解答

    针对上面的代码示例,我们可以分析下打印结果:

    1. 执行main()方法,由于JVM中之前没有Test3.class信息,因此需要加载类Test3的Class文件到JVM中。

    2. 根据类的加载原理,先加载静态内容,再加载非静态内容,因此首先加载的就是

    public static Test3 t = new Test3();

    这是一个静态实例化的代码,根据对象的创建流程,一步一步的执行,会在加载对应的构造方法时,执行隐式三步:Test3无显示继承的父类(默认继承超类Object),无非静态的成员变量,有非静态的构造代码块 --> 执行非静态的构造代码块,打印 "blockA"。

    3. 第一个static 加载完成之后,继续往下执行其他的static,执行静态代码块,打印 "blockB"。

    4. 类的加载完成

    5. 回来执行main()方法中的 Test3 t1 = new Test3(); 执行隐式三步,得到打印结果:"blockA"。

    因此最终的输出结果为:

    1 blockA
    2 blockB
    3 blockA
  • 相关阅读:
    iOS crash 追终 ,iOS 如何定位crash 位置
    ios 性能优化策略
    如何提升代码编译的速度 iOS
    关于iOS的runtime
    iOS __block 与 __weak
    spring-boot-framework 如何自动将对象返回成json格式
    spring-boot 热部署 intellij IDE(开发过程)
    MAVEN中的插件放在哪个dependcies里面
    css3 RGBA
    css3 loading 效果3
  • 原文地址:https://www.cnblogs.com/study-everyday/p/7026410.html
Copyright © 2020-2023  润新知