一个程序带你了解java初始化

Posted on Posted in JAVA

作者: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.在类的内部域的初始化是最先进行的,然后才调用构造函数。

所学有限,如有错误,欢迎指正。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注