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

开始我们先来看一段代码

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(); 
            
    }
}

运行结果:image

我们可以看出静态代码优先于普通代码快更优先与构造函数。同时静态代码块在对象创建前就运行了静态代码块,总是先运行父类代码再运行子类代码,我们也可以说父类代码先行于子类代码块。而在给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种

转载于:https://www.cnblogs.com/boWatermelon/p/6896690.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值