类加载之初始化(包括静态代码块讲解)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类加载之初始化(包括静态代码块讲解)相关的知识,希望对你有一定的参考价值。

开始我们先来看一段代码

package classLoader;

class a {
    public a() {
        System.out.println("init a");
    }
    
    public void say(){
        System.out.println("say a");
    }
    
    {
        System.out.println("block a");
    }
    
    static {
        System.out.println("static a");
    }    
}

public class b extends a {
    
    public b() {
        System.out.println("init b");
    }
    
    {
        System.out.println("block b");
    }
    
    public void say(){
        System.out.println("say b");
    }
    
    static {
        System.out.println("static b");
    }        
    
    public static void main(String[] args) {
        System.out.println("主程序开始!");
        a test = new b();  //进行类的初始化
        test.say();
        System.out.println("重新创建对象!");
        test = new b(); 
            
    }
}

运行结果:技术分享

我们可以看出静态代码优先于普通代码快更优先与构造函数。同时静态代码块在对象创建前就运行了静态代码块,总是先运行父类代码再运行子类代码,我们也可以说父类代码先行于子类代码块。而在给test重新赋予一个新的a对象时并没有执行静态代码快。接下来我们来分析出现这些现象的原因。

 

首先我们先来聊聊类的初始化

java虚拟机对于5种情况必须进行初始化。

  1. 使用new关键字实例化对象吗,读取或设置一个静态字段,以及调用一个静态方法
  2. 进行反射调用的时候,如果没有进行初始化先触发其初始化。
  3. 初始化一个类时,发现其父类没有进行初始化,则需要先进性父类的初始化。
  4. 虚拟机启动需要执行一个主类时(包含main()方法的类)。
  5. 使用jdk1.7的动态语言支持时如果一个MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的句柄时,并且其没有进行初始化则先出发其初始化

在准备阶段进行系统要求的初始值赋值。而在初始化阶段执行类构造器<clinit>()方法的过程。。

<clinit>()所发挥的作用

<clinit>()是初始化阶段主要执行的代码。根据程序员的要求进行变量的赋值和其他资源的调用。<clinit>()方法会自动收集所有类变量赋值和静态代码块。该方法与构造函数不同,他不需要显式的调用父类构造器。在执行子类的<clinit>()方法时父类的<clinit>()已经执行完毕。也就意味着父类的构造器先行于子类的构造器。所以会先输出父类静态代码块的内容,再输出子类静态代码块的内容。

注意:<clinit>()方法不是必须的,如果没有静态代码,块也没有变量的赋值。那么其可以不生成<clinit>()方法

<clinit>()是线程安全的,但如果一个县城的<clinit>()耗时很长会导致多个进程阻塞。也就是说stati代码块应用不当会造成进程阻塞。

Q&A


在给test重新赋予一个新的a对象时并没有执行静态代码快的原因?

该类已经初始化了,不用再进行初始化,故不需要进行初始化,也就不需要执行<clinit>(),自然也就不会输出静态代码的内容。

静态代码块,普通代码块,构造函数运行顺序?

由程序运行结果可知:静态代码块>普通代码块>构造函数

注意;父类代码先行于子类代码,代码进行初始化5种情况的第3种

以上是关于类加载之初始化(包括静态代码块讲解)的主要内容,如果未能解决你的问题,请参考以下文章

java第五章:面向对象(oop)之 static关键字

方法重写实现多态

Java之代码块

java中的静态代码块、代码块、构造器的执行顺序是怎样呢,这三者有啥作用呢

代码块

Java面向对象 类的成员之代码块的详解