关于java文件加载和初始化顺序问题分析

结合实际代码分析

package com.gt.world.oa.aaa;

/**
 * 
 * @author GT
 */
public class Test20140331 {
    public static int k = 0;
    public static Test20140331 t1 = new Test20140331("t1");
    public static Test20140331 t2 = new Test20140331("t2");
    public static int i = print("i");
    public static int n = 99;
     
    public int j = print("j");
     
    {
        print("构造块");
    }
     
    static {
        print("静态块");
    }
 
    public Test20140331(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }
 
    private static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "   n=" + n);
        ++n;
        return ++i;
    }
 
    public static void main(String[] args) {
    	Test20140331 t = new Test20140331("init");
    	
    	Test20140331 t2 = new Test20140331("init2");
    	
    }
 
}

/**
 *  
 *  1 程序从main函数开始执行 ,执行main函数,需要先加载class文件
 *	2 加载class文件的同时,同时初始化static成员变量和static块,执行顺序为从上到下依次执行
 *	3 加载class完成之后,初始化成员变量。注:普通代码块,可以看作成员变量,执行顺序为从上到下依次执行
 *	4 上面的过程完成之后,再从main函数的第一条语句开始执行。
 *	5 注:静态成员变量和静态代码块只会 在加载class文件的时候 执行一次
 *
 *  总结:  首先加载class文件,同时初始化static成员变量,初始化 非static成员变量,执行构造函数
 *        如果该类有父类,则按照如上顺序,从父类开始执行。
 *        
 *  补充,该例中在加载class文件的同时,初始化static成员变量,执行到 
 *           public static Test20140331 t1 = new Test20140331("t1");
 *  按道理来讲,需要按照总结的那样,先去加载class文件........
 *  这样就会出现死循环,所以,会跳到下一步执行,就是初始化非static成员变量,然后再执行构造函数。
 *
 */

/**
 * public static Test20140331 t1 = new Test20140331("t1");
 * 1>  1:j         i=0    n=0
 * 2>  2:构造块     i=1    n=1
 * 3>  3:t1        i=2    n=2
 * 
 * public static Test20140331 t2 = new Test20140331("t2");
 * 4>  4:j         i=3    n=3
 * 5>  5:构造块     i=4    n=4
 * 6>  6:t2        i=5    n=5
 * 
 * public static int i = print("i");
 * 7>  7:i         i=6    n=6
 * 
 * public static int n = 99;
 * 8>  n=99
 * 
 *     static {
	        print("静态块");
	    }
 * 9>   8:静态块    i=7    n=99
 * 
 * Test20140331 t = new Test20140331("init");
 * 10>  9:j         i=8    n=100
 * 11>  10:构造块     i=9    n=101
 * 12>  11:init      i=10    n=102
 * 
 *  * Test20140331 t = new Test20140331("init2");
 * 13>  12:j         i=11     n=103
 * 14>  13:构造块     i=12     n=104
 * 15>  14:init2      i=13    n=105
 * 
 */



package com.asp;

/**
 * 
 * @author 
 * 
 * 按照前面代码的分析
 * 猜测运行结果应该是  10,20    但是 实际结果却是:0  ,20
 * 
 * 先按照前面的例子分析,
 * 先加载class文件,同时初始化静态成员变量(此类中没有static成员变量)
 * 接着 new B(),B存在父类A,所以 先初始化A的非静态成员变量成员a,此时a(A) 已经被初始化为10,然后执行A的构造函数,
 * 接着 初始化B 中的非静态成员变量 a,此时a(B)已经被初始化为 20,然后执行B的构造函数。
 * 
 * 按照分析,确实应该打印出 10  20 的,可结果怎么会是 0  20 呢?
 * 注意一点:父类A 中的 show()函数 被子类B 覆盖了,则A构造函数中调用的show()方法不再是A中的show 而是子类 B的show(),
 * 子类B的show() 打印的是a(B) ,此时的a(B)还没有初始化,所以 打印 0. 
 * 
 * 总结:new  子类,在执行父类的构造方法的时候,父类构造方法中调用的函数如果被子类覆盖,则父类会调用该方法的子类实现。
 *
 */

 class A {
	private int a = 10;

	public A() {
		show();
		System.out.println("a = "+a);
	}

	public void show() {
		System.out.print("a = "+a+"   ");
	}

	
}

public class B extends A {
	private int a = 20;

	public B() {
		show();
		System.out.println("a = "+a);
	}

	public void show() {
		System.out.print("bbb = "+a+"   ");
	}
	
	public static void main(String[] args) {
		A b = new B();
		System.out.println(b);
	}

}








你可能感兴趣的:(关于java文件加载和初始化顺序问题分析)