实列+JVM讲解类的实列化顺序

刨根问底---类的实列化顺序

开篇三问

  • 1什么是类的加载,类的加载和类的实列有什么关系,什么时候类加载

  • 2类加载会调用构造函数吗,什么时候调用构造函数

  • 3什么是实列化对象,实列化的对象有什么东西。
    我们先做一个实验,截图来自:https://blog.csdn.net/u011517841/article/details/82657047
    public class Text {
    public static int k = 10;
    public int a = print("a");
    public static int b = print("b");
    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");
    public int m = print("m");

        {
            print("构造块");
        }
        static {
            print("静态块");
        }
        
        public int l = print("l");
        public static int o = print("o");
        
        public Text(String str) {
            System.out.println("构造:" + (++k) + ":" + str + "   i=" + i + "    n=" + n);
            ++i;
            ++n;
        }
     
        public static int print(String str) {
            System.out.println("print:" + (++k) + ":" + str + "   i=" + i + "    n=" + n);
            ++n;
            return ++i;
        }
        
        public int p = print("p");
     
        public static void main(String args[]) {
            Text t = new Text("init");
        }
    }
    

    结果:
    print:11:b i=0 n=0
    print:12:a i=1 n=1
    print:13:j i=2 n=2
    print:14:m i=3 n=3
    print:15:构造块 i=4 n=4
    print:16:l i=5 n=5
    print:17:p i=6 n=6
    构造:18:t1 i=7 n=7
    print:19:a i=8 n=8
    print:20:j i=9 n=9
    print:21:m i=10 n=10
    print:22:构造块 i=11 n=11
    print:23:l i=12 n=12
    print:24:p i=13 n=13
    构造:25:t2 i=14 n=14
    print:26:i i=15 n=15
    print:27:静态块 i=16 n=99
    print:28:o i=17 n=100
    print:29:a i=18 n=101
    print:30:j i=19 n=102
    print:31:m i=20 n=103
    print:32:构造块 i=21 n=104
    print:33:l i=22 n=105
    print:34:p i=23 n=106
    构造:35:init i=24 n=107

    分析:
    1.首先程序启动时会去找main函数吧,要想使用main函数首先会对有此main函数的类进行加载,验证,准备,初始 化。准备的时候会为类变量分配内存,初始化为默认值。因此准备的时候只会去加载静态变量。此阶段没有打印值

    2.初始化阶段:初始化阶段会为静态变量赋值和运行静态代码块。此阶段会print(b),然后new Text("text1).
      在碰到new 的时候回去初始化一个Text对象。因此会打印a,j,m,会执行代码块打印构块,然后打印l,p最后再调用构造函数。紧接着new Test("text2)就同理了。然后紧接着又继续类的初始化阶段打印i,静态块,o
      
    3.生成对象:就是初始化类的实列成员,然后调用构造函数的过程。
    

    增加有父类的情况
    public class JVMParent {

    	 public static int width = 100;
    	 
    	 public static int count;
    	 
    	 {
    		 System.out.println("parent no static code block :" + count);
    	 }
    	 
    	 static{
    		 System.out.println("parent static's count:" + count);
    	 }
    	 
    	 JVMParent(int a){
    		 System.out.println("parent init one parameter");
    	 }
    	 
    	 JVMParent(){
    		 System.out.println("parent init");
    	 }
    	 
    }
    public class JVMSon extends JVMParent {
    	
    	 
    	 {
    		 System.out.println("son no static code block :" + count);
    	 }
     
    	static {
    		System.out.println("son static 1");
    	}
     
    	public static int count1;
     
     
    	JVMSon() {
    		System.out.println("son init:" + count);
    	}
     
    	static {
    		System.out.println("son static 2");
    	}
     
    	public static void main(String[] args) {
    		System.out.println("son main start");
    		JVMSon a = new JVMSon();
     
    	}
     
    }
    

    答案
    parent static's count:0
    son static 1
    son static 2
    son main start
    parent no static code block :0
    parent init
    son no static code block :0
    分析
    1.首先要加载Son类,因为它有main函数,但是它有父类,必须先加载父类。因此先加载父类,准备,初始化,然后解析。准备阶段打印:parent static's count。然后加载子类,打印son static 1,son static 2.现在类的准备阶段完毕。
    2.执行main函数:打印son main start
    3.实列化对象:先初始化父类,parent no static code block :0,调用父类的构造函数,然后初始化子类。
    感觉这部分逻辑有问题。。。。。。

posted @ 2019-08-20 09:44  李成洪  阅读(186)  评论(0编辑  收藏  举报