结合实际代码分析
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);
}
}