美文网首页jvm
Java类加载顺序

Java类加载顺序

作者: 今晚打肉山 | 来源:发表于2017-08-30 23:50 被阅读25次

先看一段代码:

public class Text {
    public static int k = 0;
    public static Text t1 = new Text("t1");
    public static Text t2 = new Text("t2");
    public static int i = print("i");
    public static int n = 99;
    public int j = print("j");

    {
        print("构造块");
    }
    static {
        print("静态块");
    }

    public Text(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String args[]) {
        Text t = new Text("init");
    }
}

输出结果为:
1:j i=0 n=0
2:构造块 i=1 n=1
3:t1 i=2 n=2
4:j i=3 n=3
5:构造块 i=4 n=4
6:t2 i=5 n=5
7:i i=6 n=6
8:静态块 i=7 n=99
9:j i=8 n=100
10:构造块 i=9 n=101
11:init i=10 n=102

加载过程分析

执行main时,先加载所在类,声明静态变量,并初始化静态变量执行静态代码块(按顺序执行)

初始化到t1时,暂停类加载,先实例化,此时k=0,而i,n都未初始化,系统默认值为0
初始化j时,k自增为1,i,n为0,输出“1:j i=0 n=0”,n,i自增为1
执行代码块,输出“2:构造块 i=1 n=1”,n,i自增为2
执行构造函数,输出“3:t1 i=2 n=2”,n,i自增为3

初始化到t2时,暂停类加载,先实例化,此时k=3,i,n都还未初始化,但已自增为3
初始化j时,k自增为4,i,n未初始化为3,输出“4:j i=3 n=3”,n,i自增为4
执行代码块,输出“5:构造块 i=4 n=4”,n,i自增为5
执行构造函数,输出“6:t2 i=5 n=5”,n,i自增为6

初始化i,输出“7:i i=6 n=6”,n,i自增为7,返回自增后的i赋值给i
初始化n,赋值99
执行静态块,输出“8:静态块 i=7 n=99”,i自增为8,n自增为100

完成类加载,执行Text t = new Text("init");
初始化成员变量j,输出9:j i=8 n=100
调用构造块和构造方法,输出 10:构造块 i=9 n=101
11:init i=10 n=102

涉及要点

1.类加载过程
加载某类前先加载其父类
加载某类时,先声明静态成员变量,初始化为默认值,再初始化静态成员变量执行静态代码块
初始化静态成员变量执行静态代码块时,是按顺序执行(初始化静态成员变量的本质就是静态代码块)

2.实例化过程
对某类实例化前,先对其父类进行实例化
实例化某类时,先声明成员变量,初始化为默认值,再初始化成员变量执行代码块
初始化成员变量执行代码块时,是按顺序执行

3.在某类加载过程中调用了本类实例化过程(如new了本类对象),则会暂停类加载过程先执行实例化过程,执行完毕再回到类加载过程

类的主动使用与被动使用

主动使用例子:

1):最为常用的new一个类的实例对象
2):直接调用类的静态方法。
3):操作该类或接口中声明的非编译期常量静态字段
4):反射调用一个类的方法。
5):初始化一个类的子类的时候,父类也相当于被程序主动调用了
(如果调用子类的静态变量是从父类继承过来并没有复写的,那么也就相当于只用到了父类的东东,和子类无关,
所以这个时候子类不需要进行类初始化)。
6):直接运行一个main函数入口的类。

所有的JVM实现,在首次主动使用某类的时候才会加载该类。

被动使用例子:

1):子类调用父类的静态变量,子类不会被初始化。只有父类被初始化。对于静态字段,只有直接定义这个字段的类才会被初始化.
2):通过数组定义来引用类,不会触发类的初始化,如SubClass[] sca = new SubClass[10];
3):访问类的编译期常量,不会初始化类

相关文章

  • 安卓面试概要点

    Java基础 访问修饰符 √ 类加载深入理解Java类加载器ClassLoaderJava中类加载的执行顺序 泛型...

  • 类初始化和加载过程

    一、对象的初始化顺序: java类加载器加载类的顺序:http://blog.csdn.net/crazycode...

  • JAVA的类加载顺序

    理解关于java类的加载顺序 首先来捋一捋java类的加载顺序吧 父类静态代码块 》》静态代码初始化,静态属性(带...

  • Java类加载顺序

    先看一段代码: 输出结果为:1:j i=0 n=02:构造块 i=1 n=13:t1 i=...

  • Java类加载顺序

    很长时间没看这方面的内容了,写篇文章让自己牢记一下,顺便分享一下。 首先,写代码以便检验结果。测试代码: 子类代码...

  • java lang包下ClassLoader类

    类的加载顺序 code···package core.java.lang; /** @author DGW @da...

  • 《深度拆解Java虚拟机》之Java虚拟机是如何加载Java类的

    一、JVM的类加载 Java 虚拟机中的类加载,从 class 字节码文件到内存中的类,按先后顺序需要经过加载、链...

  • 类加载机制

    目录 概念 加载过程 初始化时机 类初始化顺序注意点 双亲委派模型 自定义类加载器 类加载 概念 Java虚拟机把...

  • Java类加载与初始化

    今天复习了一下java类加载时的初始化顺序,先记录一下心得,代码后续补上。 类加载时的初始化顺序 1、一般来说,类...

  • jar包包含相同类引起的诡异bug

    java类加载顺序可能不一样,所以运行结果也不可预测

网友评论

    本文标题:Java类加载顺序

    本文链接:https://www.haomeiwen.com/subject/eydfjxtx.html