深入理解JVM之类加载器(二)

类的初始化详解

       在深入理解JVM之类加载器(一)里面我主要介绍了JVM中关于类的加载相关的一些知识,那在本文我将详细介绍类的初始过程。我先编写三个类,代码如下:

public class MyTest {

    public static void main(String[] args) {
      
        System.out.printf(MyChild1.str);
//      System.out.printf(MyChild1.str2);
    }

}

class MyParent{
    public static String str="hello world";

    static {
        System.out.println("this is MyParent static");
    }
}
class MyChild extends MyParent{
    public static String str2="welcome!!";

    static {
        System.out.println("this is MyChild static");
    }
}

三个类的类名分别为MyTest,MyParent , MyChild。其中MyChild是MyParent的子类,而MyTest拥有main方法,是一个启动类。

首先我们在MyTest这个类中运行一下如下代码:

System.out.printf(MyChild.str);

输出结果为:

this is MyParent static
hello world

 接着把刚才的代码改为如下代码再运行:

System.out.printf(MyChild.str2)

输出结果为:

this is MyParent static
this is MyChild static
welcome!!

 结果分析:

        第一次我们通过MyChild这个类调用它父类MyParent中的str这个静态变量,输出结果表明在执行 MyChild.str 时,执行了MyParent这个类中定义的静态代码块,但是没有执行MyChild中的静态代码块。而在第二次运行时我们将str换成了MyChild这个类中定义的静态变量str2,从输出结果看出,此时代码在运行时先执行了MyParent这个类中的静态代码块,接着执行了MyChild中的静态代码块,最后才输出了str2的值。从以上分析我们得出结论:

  • 对于静态字段来说,调用时只有直接定义了该字段的类才会被初始化:在第一次运行时,我们访问了MyParent中的静态变量,即我们对MyParent这个类进行了主动使用,但是没有访问MyChild中的静态变量,所以并没有主动使用MyChild这个类,因此MyChild中的静态代码块不会执行。总之,谁定义了静态变量,使用这个静态变量时就表示对谁的主动使用。
  • 当一个类在初始化时,要求其父类全部初始化完毕后,该类才会被初始化:在第二次运行时,我们访问了MyChild中的静态变量,则主动使用了MyChild这个类,所以MyChild中的静态代码块被执行了,但是却先执行了MyParent中的静态代码块,这是因为MyChild是MyParent的子类,当初始化一个类的子类时父类也会主动使用。这一点我们可以通过配置虚拟机参数         -XX:+TraceClassLoding(用于追踪类的加载信息并按顺序打印出来)观察得出,idea中配置方法如图:

 具体加载信息由于篇幅太长我就不贴出来了,可自行配置并运行程序观察。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值