现在的位置: 首页 > 综合 > 正文

java 类加载和初始化的那点秘密

2018年02月04日 ⁄ 综合 ⁄ 共 1592字 ⁄ 字号 评论关闭
先看看下面的这段代码,这个例子将说明类加载的顺序。也可以直接略过代码,直接看下面的图:
class GrandFather{
GrandFather(){
System.out.println("the GrandFather constructor is initialized");
}
static{
System.out.println("the GrandFather static filed is initialized");
}
}

class Father extends GrandFather{
Father(){
System.out.println("the Father constructor is initialized!");
}
static{
System.out.println("the Father static filed is initialized");
}
}

public class Son extends Father {
public Son(){
System.out.println("the Son constructor is initialized");
}
static{
System.out.println("the Son static filed is  initialized");
}
public static void main(String[] args) {
Son son = new Son();
}
}
为了更直观的说明,将上面的代码转化成下面的图:


将上面的代码运行,得出的结果是:

the GrandFather static filed is initialized
the Father static filed is initialized
the Son static filed id initialized
the GrandFather constructor is initialized
the Father constructor is initialized!
the Son constructor is initialized

怎么样,看了上面的运行结果,心里是不是有点小感觉了已经?下面用文字总结下:
1,在Son上运行java时,第一件事情就是试图访问Son的main方法(一个static方法)。于是加载器开始启动并找出Son类的编译代码(在名为Son.class的文件中)。
2,在对Son类进行加载的过程中,编译器注意到它有个基类(这是又关键字extends知道的),这里为Father,于是继续加载Father类。如果该基类还有其自身的基类,这里有个GrandFather类,于是GrandFather也被加载。如此类推。
3,接下来,根基类中static(包括static方法,变量,域)初始化,然后是下一个导出类,以此类推。这里static初始化的顺序是GrandFather>Father>Son。至于为什么要从根基类开始初始化,不难想到是因为 导出类的static初始化可能依赖于基类成员能否被正确初始化。
4,经过上面几步,必要的类都加载完毕,对象就可以被创建了。
    a,首先,对象中所有的基本类型都会被设为默认值,对象引用被设为NULL(对于这一点,再看看下面给出的例子)
    b,然后,基类的构造器会被调用
    c,最后,构造器的其余部分被调用
public class Test
{
 /**
     * @param args
     */
    private int i=getValue();//第2行
    private int j = 10;
    int getValue(){
        return j;
    }
    public static void main(String[] args) {
        System.out.print(new Test().i);//第9行

    }
}
很显然,这个例子在执行到上面的第4步时,只执行了a,b两步,而第三步 private int j = 10,在i被调用时还没被执行

抱歉!评论已关闭.