作者:faaronzheng 转载请注明出处!
下面一段java代码我认为能较完整的展现java初始化过程。
class MyPrint
{
MyPrint(int i)
{
System.out.println("MyPrint"+i);
}
}
class Init
{
class Inner
{
Inner()
{
System.out.println("innerclass");
}
}
Init()
{
System.out.println("baseClass");
}
static MyPrint p1=new MyPrint(1);
MyPrint p=new MyPrint(2);
}
class Init1 extends Init
{
MyPrint p=new MyPrint(3);
static MyPrint p1=new MyPrint(4);
public Init1()
{
System.out.println("extendClass");
}
}
public class InitOrder {
Init1 init1=new Init1(); //和下面一句位置交换一下就会有区别
Init init=new Init();
// Init.Inner in=init.new Inner();
static MyPrint p1=new MyPrint(5);
InitOrder()
{
System.out.println("GouZao");
}
MyPrint p=new MyPrint(6);
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("hello");
InitOrder io=new InitOrder();
}
// static Init i=new Init();
}
在解释初始化过程前首先说明下列几个问题
1.类加载完后,对象才可以创建。
2.加载类主要就是对静态成员变量和方法进行初始化。
3. 静态域只会初始化一次。
这段代码的执行结果是什么呢?
首先,java编译器会寻找到程序的入口点mian()。要执行main()方法(静态),必须要加载InitOrder类。类中静态域会最先初始化,所以首先会打印一个MyPrint5。之后调用main()方法,打印一个hello,接下来执行
InitOrder io=new InitOrder();
创建io对象(InitOrder类已加载),
类内部域的初始化是最先进行的,然后才调用构造函数。所以会执行
Init1 init1=new Init1();
创建init1对象(这时Init1还未加载),并且Init1是继承自Init的,我们要知道
存在继承关系的情况下,会先加载基类。所以会先初始化根基类中的静态域,接下来初始化导出类中的静态域。结果会先打印MyPrint1,再打印MyPrint4。类加载完毕后,对象就可以被创建了。因为
存在继承关系,所以会先初始化基类,打印出MyPrint2和baseClass。
基类初始化完后,就会初始化导出类,所以会打印MyPrint3和extendClass。至此,init1对象创建并初始化完了。然后执行
Init init=new Init();
创建init对象(这时Init已加载)因为静态域只会初始化一次,所以打印MyPrint2和baseClass。接下来执行
MyPrint p=new MyPrint(6);
打印MyPrint6。最后调用InitOrder类的构造函数打印GouZao。至此,io对象创建并初始化完毕。一个完整的初始化过程结束了。这时你会发现程序中还有一个注释和两条被注释掉的语句。
Init1 init1=new Init1(); //和下面一句位置交换一下就会有区别
Init init=new Init();
交换位置后主要的变化在于先执行
Init init=new Init();
时不会打印MyPrint4。主要想表明加载类时才会对静态成员变量和方法进行初始化,显然这里不会加载Init1。
至于第一条被注释掉的语句只想说明内部类并不是外围类的域,内部类也只有创建对象时才会初始化。至于第二条被注释的语句,相信你了解了前面的内容后也可以知道答案。
最后总结几条原则:
1.只要类被加载,静态域一定最先初始化。
2.存在继承关系的情况下,先加载基类,在加载导出类。
3.初始化对象时,先初始化基类,在初始化导出类。
4.在类的内部域的初始化是最先进行的,然后才调用构造函数。
所学有限,如有错误,欢迎指正。