Java 触发类加载的六大时机! | CSDN 博文精选

2017-03-19
作者 | weiwenhou

责编 | 刘静

出品 | CSDN博客


前言


什么情况下会触发类加载的进行呢?本文将结合代码demo谈谈几种情况,希望对大家有帮助。


类加载时机


什么情况需要开始类加载过程的第一阶段:加载?Java虚拟机规范中并没有进行强制约束,这点可以交给虚拟机的具体实现来自由把握。但是对于初始化阶段,虚拟机规范则严格规定了以下几种情况必须立即对类进行初始化,如果类没有进行过初始化,则需要先触发其初始化。


创建类的实例


为了验证类加载,我们先配置一个JVM参数
-XX:+TraceClassLoading 监控类的加载

在IDE配置如下:

demo代码:

public class ClassLoadInstance {    
    static {    
        System.out.println("ClassLoadInstance类初始化时就会被执行!");    
    }    
    public ClassLoadInstance({    
      System.out.println("ClassLoadInstance构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args{    
        ClassLoadInstance instance = new ClassLoadInstance();    
    }    
}

运行结果:

结论:

new ClassLoadInstance实例时,发现ClassLoadInstance被加载了,因此 new创建实例对象,会触发类加载进行。
访问类的静态变量
demo代码:
public class ClassLoadStaticVariable {    
    static {    
        System.out.println("ClassLoadStaticVariable类初始化时就会被执行!");    
    }    
    public static int i = 100;    
    public ClassLoadStaticVariable({    
      System.out.println("ClassLoadStaticVariable构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args{    
        System.out.println(ClassLoadStaticVariable.i);    
    }    
}

运行结果:

结论:

访问类ClassLoadStaticVariable的静态变量i时,发现ClassLoadStaticVariable类被加载啦,因此访问类的静态变量会触发类加载。
注意:
访问final修饰的静态变量时,不会触发类加载,因为在编译期已经将此常量放在常量池了。


访问类的静态方法


demo代码:
public class ClassLoadStaticMethod {    
    static {    
        System.out.println("ClassLoadStaticMethod类初始化时就会被执行!");    
    }    
    public static void method(){    
        System.out.println("静态方法被调用");    
    }    
    public ClassLoadStaticMethod({    
      System.out.println("ClassLoadStaticMethod构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args{    
        ClassLoadStaticMethod.method();    
    }    
}

运行结果:

结论:

访问类ClassLoadStaticMethod的静态方法method时,发现ClassLoadStaticMethod类被加载啦,因此访问类的静态方法会触发类加载。


反射


demo代码:
package classload;    
public class ClassLoadStaticReflect {    
    static {    
        System.out.println("ClassLoadStaticReflect类初始化时就会被执行!");    
    }    
    public static void method(){    
        System.out.println("静态方法被调用");    
    }    
    public ClassLoadStaticReflect({    
      System.out.println("ClassLoadStaticReflect构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args) throws ClassNotFoundException {    
        Class.forName("classload.ClassLoadStaticReflect");    
    }    
}

运行结果:

结论:

反射得到类ClassLoadStaticReflect时,发现ClassLoadStaticReflect类被加载啦,因此反射会触发类加载。


当初始化一个类时,发现其父类还未初始化,则先触发父类的初始化


demo代码:
//父类    
public class ClassLoadSuper {    
    static {    
        System.out.println("ClassLoadSuper类初始化时就会被执行!这是父类");    
    }    
    public static int superNum = 100;    
    public ClassLoadSuper({    
        System.out.println("父类ClassLoadSuper构造函数!");    
    }    
}    
//子类    
public class ClassLoadSub extends ClassLoadSuper {    
    static {    
        System.out.println("ClassLoadSub类初始化时就会被执行!这是子类");    
    }    
    public static int subNum = 100;    
    public ClassLoadSub({    
        System.out.println("子类ClassLoadSub构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args) throws ClassNotFoundException {    
        ClassLoadSub classLoadSub = new ClassLoadSub();    
    }    
}

运行结果:

看了运行结果,是不是发现,网上那道经典面试题(讲讲类的实例化顺序?)也很清晰啦。先父类静态变量/静态代码块-> 再子类静态变量/静态代码块->父类构造器->子类构造器

结论:
实例化子类ClassLoadSub的时候,发现父类ClassLoadSuper先被加载,因此当初始化一个类时,发现其父类还未初始化,则先触发父类的初始化


虚拟机启动时,定义了main()方法的那个类先初始化


demo代码:
package classload;    
public class ClassLoadTest {    
    public static void main(String[] args)  {    
       System.out.println(ClassLoadSub.subNum);    
    }    
}

运行结果:

结论:

虚拟机启动时,即使有ClassLoadSub,ClassLoadSuper,ClassLoadTest等类被加载, 但ClassLoadTest最先被加载,即定义了main()方法的那个类会先触发类加载。


练习与小结


触发类加载的六大时机,我们都分析完啦,是不是不做个题都觉得意犹未尽呢?接下来,我们来分析类加载一道经典面试题吧。
class SingleTon {      
    private static SingleTon singleTon = new SingleTon();      
    public static int count1;      
    public static int count2 = 0;      
    private SingleTon({      
        count1++;      
        count2++;      
    }      
    public static SingleTon getInstance({      
        return singleTon;      
    }      
}      
public class ClassLoadTest {      
    public static void main(String[] args{      
        SingleTon singleTon = SingleTon.getInstance();      
        System.out.println("count1=" + singleTon.count1);      
        System.out.println("count2=" + singleTon.count2);      
    }      
}  
运行结果:

分析:

SingleTon.getInstance(),调用静态方法,触发SingleTon类加载。
SingleTon类加载初始化,按顺序初始化静态变量。
先执行private static SingleTon singleTon = new SingleTon(); ,调用构造器后,count1,count2均为1;
按顺序执行 public static int count1; 没有赋值,所以count1依旧为1;
按顺序执行 public static int count2 = 0;所以count2变为0.
版权声明:本文为CSDN博主「weiwenhou的原创文章。
扫描下方二维码,查看博主精彩分享!
想学习物联网不知道从哪开始学?敲门砖的物联网接入技术或是其一。本次公开课邀请到拥有13年从业经验的翰云科技研发总监段奇,深入剖析物联网接入技术,物联网平台架构设计以及实践,立即扫码报名!
 热 文 推 荐 

点击阅读原文,精彩继续。
你点的每个“在看”,我都认真当成了喜欢

相关文章

¥250,000 | java中级工程师6人驻场

2021-10-02
有Java的常用开发模式及相关框架有相关的开发经验.能够独立完成功能模块(高质量的代码.在效率和健壮性上有高的追求);4.熟...

把Autofac玩的和javaSpring一样6

2021-10-02
Java的 Spring注解方式开发思想,所有autofac容器的注册 和 装配 都是依赖标签来完成.这样一来 一方面很容易分清楚 哪些是DI 哪些...

从日语专业的文科大学生到Java开发工程师, 这6个月我经历了什么?

2021-10-02
今天,安妹要给大家分享的是一位学文科的小哥哥如何转行成为一名Java开发工程师的故事.他如何走出迷茫的大学时期,找到人生的...

巧用Java8中的Stream,让集合操作6到飞起!!!

2021-10-02
来自:掘金(作者:坚持就是胜利)原文链接:https://juejin.im/post/5d5e2616f265da03b638b28a简介java8也出来好久了,接口默认方...

石家庄招聘|迈特望科技招聘(需求分析/Java开发,月薪6-10K)

2021-10-02
Java开发工程师(6-10K)任职要求:1、熟练掌握Java、JavaScript等开发语言;2、能够使用Spring、Spring boot、Mybatis等主流框...

儿童节,一起回顾塞班时代的6款经典Java游戏

2021-10-02
那时,塞班内置的Java游戏虽然没有联机要素,却也带给我们不少的欢乐.而从2009年开始,由于安卓设备的普及,曾经红极一时的...

20日/21日免费直播:Java、运维、嵌入式等6大课程,高薪!人才紧缺!

2021-10-02
5月20日免费直播课长按图片识别二维码报名5月21日免费直播课长按图片识别二维码报名达内课程方向涵盖IT行业所有方向,包含Java...

7月6日汇才创智联合岭南师范学院开展Java暑期训练营

2021-10-02
java训练营(一)项目环境和规范java训练营(二)Java基础java训练营(三) 编写、编译、运行 java训练营(四) 利器(IDE工具)...

‫Java_ 6 |تۈرنى ئەمەلىيلەش ۋە قۇرۇلما ئۇسۇلىنى ئىشلىتىش

2021-10-02
مۇناسىۋەتلىك مەزمۇنلار:‫Java پىروگرامما تىلىدىن ئاساس - يازمىلىقJava ...

Hello Java | 第十二期:Java面向对象程序设计(六)

2021-10-02
一、Java的名字空间Java中没有全局方法和全局变量.所有的变量和方法都是在类中定义的,而且还是类的重要组成部分,每个类又是...

随机推荐

搭建 Typecho 个人博客教程

2020-08-26
搭建# 环境安装安装宝塔 Linux 面板,复制安装代码到 Xshell 回车运行.yum install -y wget && wget -O install.sh http://download.bt.cn/...

【Mac】PhpStorm 2020 安装教程

2020-06-03
打开下载文件【PhpStorm 2020】打开安装包,把程序【PhpStorm】拖入右边的文件夹,进行安装.等待 PhpStorm 拷贝完成,即是初步完成安装PhpStorm.

工学类专业就业前景好排名

2016-12-18
计算机科学与技术计算机科学与技术是一个计算机系统与网络兼顾的计算机学科宽口径专业,旨在培养具有良好的科学素养,具有自主...

最梦幻最冒险最浪漫!上海迪士尼乐园的美妙远不止你想象的这些

2016-04-18
由米奇和唐老鸭驾驶的米奇童话专列开来了.魔法火车头的后面跟着长长的主题花车队伍,一路驶过乐园的南部主干道—— 这可是全球...

【今日猪价信息】今日猪价格表猪价行情分析预测今天猪价涨了吗2021猪价行情今日猪价涨跌表公众号今日猪价涨跌表最新走势

2016-04-09
【今日猪价信息】今日猪价格表猪价行情分析预测今天猪价涨了吗2021猪价行情今日猪价涨跌表公众号今日猪价涨跌表最新走势

100套国庆70周年源文件,位图处理快手套用,设计排版不求人

2016-03-27
今天跟大家分享100套国庆70周年源文件,位图处理快手套用,设计排版不求人.为了让大家能更稳定的下载模板,我们又开通了全新...

3月Github最热门的10个Java开源项目

2015-11-04
盘点一下Github上开源的Java面试/学习相关的仓库,看完弄懂薪资至少增加10k( 2018-12-24)可能是一份最适合你的后端面试指南(部...

10月编程语言排行榜出炉,C、C++和JAVA你会选哪个?

2015-09-06
如果一定要在C、C++和JAVA中选择,是C++、C还是java呢?从开发效率的角度而言,现如今C++的开发效率并不亚于Java,甚至有...

算法--监控二叉树

2015-01-13
监控二叉树_Mosiclone的博客-CSDN博客class getCamera{ // 递归遍历整个树 // status有三个状态:0不能被监测到,1自身装了摄像头...

支付宝小程序悄然上线 与微信如出一辙

2015-01-06
另外,支付宝小程序支持桌面快捷方式,可以将小程序直接发送到桌面,以便快速调用,这和目前合作的共享单车类似.同时,支付宝...