当java实例化对象时,首先先进行类加载,类加载的整个过程是将类字节码引入内存,并未类中的static变量赋值。
上篇文章: http://blog.csdn.net/kingherooo/article/details/38493619 已经大概分析了类的加载机制,下面讲一下类的实例化过程。
首先引入示例代码
父类
package test;
public class Fu {
public int j = 9;
public static int i = 10;
static{
i = 9;
System.out.println("Fu静态代码块");
}
{
j = 10;
System.out.println("Fu构造代码块");
}
public Fu(){
System.out.println("Fu_构造方法");
}
public int getJ() {
return j;
}
public void setJ(int j) {
this.j = j;
}
public void a(){
System.out.println("父类的a方法");
};
public static void staticMethod(){
System.out.println("fu");
}
}
子类
package test;
import com.sun.org.apache.xerces.internal.impl.xpath.regex.Match;
public class Zi extends Fu{
public int j = 0;
static {
i = 3;
System.out.println("Zi静态代码块");
}
public static int i = 2;
{
System.out.println("Zi构造代码块");
}
public Zi(){
System.out.println("Zi构造方法");
}
public void a(){
try {
throw new Exception();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("子类的a方法");
}
public int getJ() {
return j;
}
public void setJ(int j) {
this.j = j;
}
}
执行如下代码
程序打印结果为:
Fu静态代码块
Zi静态代码块
Fu构造代码块
Fu构造方法
Zi构造代码块
Zi构造方法
我们通过断点debug对其进行跟踪 得知具体的运行过程为:
首先先执行父类的静态变量赋值和静态代码块(具体执行顺序根据程序书写顺序确定)
然后执行子类的静态变量赋值和静态代码块
之后执行父类的成员变量赋值语句(在此时之前子类的成员变量被java程序赋初值 zi对象内有两个j变量 初始值都为0)
再执行父类的构造代码块
执行父类构造方法
执行子类成员赋值语句
执行子类构造代码块
执行子类构造方法
当我们执行如下语句时:
输出的结果为
父类的j的值9
子类的j的值0
子类的a方法
特别的:
当子类方法覆盖父类方法时,若父类方法没有声明抛出异常 则子类只能对可能出现异常的语句进行try—catch处理