java类加载流程

类加载流程

演示代码:

public class Demo01 {
    public static void main(String[] args) {
        Demo demo = new Demo();
        //3、创建对象
        demo.test01();
        //18、调用test01方法
    }
}

class Demo{
    static int a;
    //1、a=0
    int b;
    //4、demo.b=0
    int num2 = test01();
    //5、调用test01方法
    //9、demo.num2=1
    static{
        System.out.println("1"+a);
        //2、打印10
    }
    {
        System.out.println("2"+a);
        //10、打印21
        System.out.println("2"+b);
        //11、打印21
    }
    public Demo(){
        System.out.println("3"+a);
        //12、打印31
        System.out.println("3"+b);
        //13、打印31
        test01();
        //14、调用test01方法
    }

    public int test01(){
        System.out.println("4"+(a++));
        //6、打印40,a=1
        //15、打印41,a=2
        //19、打印42,a=3
        System.out.println("4"+(b++));
        //7、打印40,b=1
        //16、打印41,b=2
        //20、打印42,b=3
        return a;
        //8、返回1
        //17、返回2
        //21、返回3
    }
}

结果:在这里插入图片描述
1、将所有static加载的属性,代码块分配内存

2、依次对属性赋值,然后执行静态代码块

3、创建对象也是同理

4、先给成员变量划分空间,然后依次赋值

5、由于静态部分已经随着类的加载而全部加载进内存,所以不再执行。执行构造代码块

6、再执行构造函数

据说是华为n年前的题目

public class Demo02 {
    //1、将所有static修饰的属性,代码块和方法加载进内存
    //2、对static修饰的属性进行初始化
    public static int k = 0;
    //3、k=0
    public static Demo02 t1 = new Demo02("t1");
    //4、创建一个Demo02对象为t1赋值,static修饰的属性和代码块已经加载进内存,不再执行
    public static Demo02 t2 = new Demo02("t2");
    //17、与t1同理,结果为:4:j i=3 n=3;5:构造块 i=4 n=4;6:t2 i=5 n=5
    //t2.a=0 t2.j=3
    public static int i = print("i");
    //18、调用print方法,为i赋值,此时i=6
    //22、i=7
    public static int n = 99;
    //23、n=99
    private int a = 0;
    //5、k=0 t1.a=0
    public int j = print("j");
    //6、调用print(String str)为j赋值
    //t1.j=1
    {
        print("构造快");
        //10、调用print()函数
    }
    static{
        print("静态块");
        //24、调用print方法
    }
    public Demo02(String str){
        System.out.println((++k)+":"+str+"  i="+i+"  n="+n);
        //14、k=3,i=2,n=2; 3:t1 i=2 n=2
        ++i;
        //15、i=3
        ++n;
        //16、n=3
    }
    public static int print(String str){
        System.out.println((++k)+":"+str+" i="+i+" n="+n);
        //7、k=1;i,n还没赋值,默认值为0; 1:j i=0 n=0
        //11、k=2;i=1,n=1; 2:构造块 i=1 n=1
        //19、k=7;i=6,n=6;7:j i=6 n=6
        //25、k=8;i=7,n=99;8:静态块 i=7 n=99
        ++n;
        //8、n=1
        //12、n=2
        //20、n=7
        //26、n=100
        return ++i;
        //9、i=1,返回1
        //13、i=2,返回2
        //21、i=7,返回7
        //27、i=8,返回8
    }
    public static void main(String[] args) {
        //28、结束
        //i=8 n=100
    }
}

结果:在这里插入图片描述

代码执行按顺序看代码注释

1、这个面试题的难点在于static成员变量的初始化创建了一个对象,需要理解类的加载机制。


类的加载机制

类的加载机制主要分为三个部分:加载,链接,初始化。链接又可以细分为验证,准备和解析。

加载

指把class字节码文件从各个来源通过类加载器装载进内存。

验证

为了保证加载进来的字节流符合虚拟机规范,不会造成安全错误。(这个我也不懂原理,只知道有这么一回事)

准备

(面试题考点)主要为静态变量(注意不是实例变量)分配内存和赋予初值。初值,不是代码中具体写的初始化的值,而是Java虚拟机根据不同变量类型的默认初始值。如基本类型的初值就是0,引用类型初值为null,常量初值为代码中设置的值.

解释

将常量池内的符号引用替换为直接引用。(这个我也不懂原理,只知道有这么一回事)

初始化

(面试题考点)这个阶段对static修饰的变量、代码块进行初始化。如果初始化一个类的时候,其父类还没有初始化,就先对父类初始化。如果含有多个静态变量和静态代码块,就按顺序从上到下执行。


拓展:

内存主要分为四个区:

栈:栈中保存基本数据类型的变量和自定义的对象的引用(不是对象)**,**对象本身都存放在堆区中,被执行的方法的也是pull到栈中,当方法执行完后再push出栈。

堆:所有使用new创建的对象本身都存放在堆中

数据区:存放类中的方法

代码区:static变量和String常量

如果错漏,欢迎指正。

发布了5 篇原创文章 · 获赞 1 · 访问量 218

猜你喜欢

转载自blog.csdn.net/qq_41551830/article/details/104454324