Java中的类初始化解析

 更新时间:2023年08月14日 08:56:11   作者:IT_GJW  
这篇文章主要介绍了Java中的类初始化解析,类的初始化是一个Java类生命周期中的其中一个阶段,初始化是类加载的最后一个阶段,也正是在初始化阶段,才会真正开始执行类中所写的Java代码,需要的朋友可以参考下

类的初始化

类的初始化是一个Java类生命周期中的其中一个阶段。

如下图所示:

生命周期中的前五个阶段(加载、验证、准备、解析、初始化)是一个类在JVM中的完整加载过程。

初始化是类加载的最后一个阶段,也正是在初始化阶段,才会真正开始执行类中所写的Java代码。

Java虚拟机规范中严格规定了有且只有四种情况必须立即对类进行初始化:

1.遇到new、getstatic、putstatic、或者invoicestatic这4条字节码指令时,如果类没有进行过初始化,则需要触发其初始化。生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象、读取或设置一个类的静态字段(被final修饰、已在编译期就把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。

2.使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。

3.当初始化一个类的时候,如果发现父类还没有进行过初始化,需要先触发其父类的初始化。

4.当虚拟机启动时,用户需要指定一个主类(包含main方法的那个类),虚拟机会先初始化这个主类。

这四种场景中的行为称为对一个类进行主动引用,除此之外引用类的方式,都不会触发初始化,被称为被动引用。

初始化一个类时,最先执行的是静态域中代码,而静态域中包含静态变量、静态块和静态方法,其中需要初始化的是静态变量和静态块,这两者的执行顺序由代码的书写顺序决定。

静态域中的代码只会被执行一次。如果是使用new关键字实例化对象,静态域中的代码被执行后,紧接着会执行构造代码块和构造函数来实例化对象,这部分代码会执行多次,每次使用new关键字实例化对象时,这部分代码都会执行。可以用如下一段程序验证这些代码的执行顺序:

public class ClassInitTest {
    public static ClassInitTest c1 = new ClassInitTest();
    public static ClassInitTest c2 = new ClassInitTest();
    {
        System.out.println("构造代码块执行");
    }
    static {
        System.out.println("静态代码块执行");
    }
    public ClassInitTest(){
        System.out.println("构造方法被执行");
    }
    public static void main(String[] args){
        System.out.println("main方法的第一行被执行");
        ClassInitTest c = new ClassInitTest();
        System.out.println("main方法的第二行被执行");
    }
}

ClassInitTest是主类,当JVM启动时会对该类进行初始化,首先初始化静态域中的代码,可以看到首先是两个静态变量c1和c2,对c1、c2声明的同时进行变量值的初始化,其值是实例对象,因此构造代码块和构造方法会被执行,new了两次,因此会被执行两次。

紧接着会执行静态代码块中的代码。静态域中的代码执行完毕后便开始执行main方法,先是输出一行语句,接着又实例化了一个对象,构造代码块和构造方法会被执行,最后又输出一行语句。因此执行的结果如下:

如果存在继承的情况,初始化子类时,会先初始化父类,同时这几类代码执行顺序的优先级保持不变。实例代码如下:

public class Father {
    static {
        System.out.println("父类的静态代码块被执行");
    }
    {
        System.out.println("父类的构造代码块被执行");
    }
    public Father(){
        System.out.println("父类的构造方法被执行");
    }
}
public class Child extends Father{
    public Child(){
        System.out.println("子类构造方法被执行");
    }
    {
        System.out.println("子类的构造代码块被执行");
    }
    static {
        System.out.println("子类的静态代码块被执行");
    }
    public static void main(String [] args){
        new Child();
    }
}

执行结果如下:

之所以子类的构造方法执行前会先执行父类的构造方法,是因为子类的构造方法总是先调用父类的某个构造方法,也就是说,如果子类没有明显地指明使用父类的哪个构造方法,子类就调用父类不带参数的构造方法。

子类中使用super关键字调用父类的构造方法,而且super必须是子类构造方法的第一条语句,如果子类构造方法中没有明显地写出super关键字调用父类的哪个构造方法,那么默认在子类构造方法中有如下语句(即使不写):

super();//调用父类的无参构造函数

当然也可以在子类的构造方法中显式地用super语句指明调用父类的哪个构造方法(如果父类有多个构造方法的话)

super(实参列表);

到此这篇关于Java中的类初始化解析的文章就介绍到这了,更多相关Java类初始化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • IDEA代码热部署和热加载的三种实现方案

    IDEA代码热部署和热加载的三种实现方案

    在日常开发中,我们需要经常修改 Java 代码,手动重启项目,查看修改后的效果,如果在项目小时,重启速度比较快,等待的时间是较短的,我们可以使用代码热加载和热部署解决该问题,本文给大家介绍了三种实现方案,需要的朋友可以参考下
    2023-11-11
  • Java 在PDF中绘制形状的两种方法

    Java 在PDF中绘制形状的两种方法

    这篇文章主要介绍了Java 在 PDF 中绘制形状的两种实现方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • 解决Maven项目pom.xml导入了Junit包还是用不了@Test注解问题

    解决Maven项目pom.xml导入了Junit包还是用不了@Test注解问题

    在Maven项目中,如果在非test目录下使用@Test注解,可能会因为pom.xml中<scope>test</scope>的设置而无法使用,正确做法是将测试代码放在src/test/java目录下,或去除<scope>test</scope>限制,这样可以确保Junit依赖正确加载并应用于适当的代码部分
    2024-10-10
  • java设计模式之工厂方法模式

    java设计模式之工厂方法模式

    这篇文章主要为大家详细介绍了java设计模式之工厂方法模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • SpringMVC超详细介绍自定义拦截器

    SpringMVC超详细介绍自定义拦截器

    Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。本文将代码演示和文字描述详解拦截器的原理与使用
    2022-06-06
  • Java 多线程传值的四种方法

    Java 多线程传值的四种方法

    这篇文章主要介绍了Java 多线程传值的四种方法,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • SpringBoot自定义全局异常处理器的问题总结

    SpringBoot自定义全局异常处理器的问题总结

    Springboot框架提供两个注解帮助我们十分方便实现全局异常处理器以及自定义异常,处理器会优先处理更具体的异常类型,如果没有找到匹配的处理器,那么它会寻找处理更一般异常类型的处理器,本文介绍SpringBoot自定义全局异常处理器的问题,一起看看吧
    2024-01-01
  • 浅析java创建文件和目录

    浅析java创建文件和目录

    这篇文章主要介绍了浅析java创建文件和目录的关键技术点以及演示示例,是篇非常不错的文章,有需要的朋友可以参考下
    2014-09-09
  • 解决spring cloud服务启动之后回到命令行会自动挂掉问题

    解决spring cloud服务启动之后回到命令行会自动挂掉问题

    这篇文章主要介绍了解决spring cloud服务启动之后回到命令行会自动挂掉问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Springcloud RestTemplate服务调用代码实例

    Springcloud RestTemplate服务调用代码实例

    这篇文章主要介绍了Springcloud RestTemplate服务调用代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08

最新评论