类加载实例代码详解

本文章用于对类加载实例代码的详解部分

代码地址
什么是类加载

前情回顾

所有的Java虚拟机必须在每个类或者接口被Java程序“首次主动使用时”才初始化它们,如果不是首次使用或非主动使用是不会被初始化的。
主动使用分为:

  • 创建类的实例
  • 访问某个类或某个接口的静态变量(助记符为getstatic),或者对它们的静态变量进行赋值(助记符为putstatic)
  • 调用类的静态方法(助记符为invokestatic)
  • 反射(如Class.forName(“com.test.Test”)
  • 初始化一个类的子类
  • Java虚拟机启动时被标明启动类的类,虚拟机启动时,用户需要指定一个要执行的主类(包含 main() 方法的那个类),虚拟机会先初始化这个主类。
  • 动态语言…
  1. 主动使用

public class MyTest1 {
    public static void main(String[] args) {
        System.out.println(MyChild1.str);//输出Myparent1 static block  Hello World
    }
}
class Myparent1{
        public static String str="Hello World";
        static {
            System.out.println("Myparent1 static block");
        }
}
class MyChild1 extends Myparent1{
    public static String str2="Hello World2";
    static {
        System.out.println("MyChild1 static block");
    }
}

解析 :在main中我们通过子类访问了父类的静态代码,会输出什么?
输出是 :Myparent1 static block Hello World
补充知识(静态代码块是在初始化的时候被执行的)
也就是先输出父类代码块中的静态代码块再输出静态字段,而子类的静态代码块并没有输出,
这说明了什么?说明了父类被初始化了而子类没有 通过子类访问父类的静态变量只会导致父类的初始化而不会导致子类的初始化

而如果直接访问子类的静态代码会输出什么呢?
即:

public class MyTest1 {
    public static void main(String[] args) {
        System.out.println(MyChild1.str2);//输出Myparent1 static block MyChild1 static block Hello World2
    }
}
class Myparent1{
        public static String str="Hello World";
        static {
            System.out.println("Myparent1 static block");
        }
}
class MyChild1 extends Myparent1{
    public static String str2="Hello World2";
    static {
        System.out.println("MyChild1 static block");
    }
}

其输出是:Myparent1 static block MyChild1 static block Hello World2
很明显,**调用子类的静态字段会导致父类和子类都初始化,也就是看做对父类的主动使用。

那么,当我们通过子类调用父类的静态字段时,子类有没有被加载呢?(不明白加载的同学看这里

我们通过设置虚拟机参数:-XX:+TraceClassLoading
这个参数表示在控制台输出虚拟机加载的类信息

[Loaded classloader.MyTest1 from file:/C:/Users/%e9%a5%b6%e7%8f%82/Desktop/jvm-learning/target/classes/]
[Loaded classloader.Myparent1 from file:/C:/Users/%e9%a5%b6%e7%8f%82/Desktop/jvm-learning/target/classes/]
[Loaded classloader.MyChild1 from file:/C:/Users/%e9%a5%b6%e7%8f%82/Desktop/jvm-learning/target/classes/]
Myparent1 static block
Hello World

以上是控制台输出的一部分,其中省去了大量片段只保留了重要的,第一行即类加载器首先加载了MyTest1,即主类,即main方法所在的类,然后加载了MyParent1,再加载了MyChild1,再进行输出

我们可以看到类加载器先加载主类,然后根据代码内容进行加载有继承关系的父类,然后才加载子类。

补充知识:

  • jvm参数

    • -XX:+<option> 开启option选项 即-XX:+TraceClassLoading,开启TraceClassLoading选项
    • -XX:-<option> 关闭option选项
    • -XX:<option>=<value> 将option选项设置为value
      https://www.cnblogs.com/czwbig/p/11127222.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值