①构造器的初始化顺序
package cai.Init;
/**
*由输出可以看到
*House类中Window对象的定义不论是在House之前还是之后,都是首先执行Window对象的定义,
*然后才开始执行Constructor的初始化,当然变量的初始化也是这样
*/
class Window {
public Window(int i){
System.out.println("The Window "+i+" is show!") ;
}
}
class House {
Window a = new Window(1); // before constructor
public House(){
System.out.println("The House is show!") ;
a = new Window(2); // in constructor
}
Window b = new Window(3); // after constructor
}
public class InitConstr {
public static void main(String[] args) {
new House();
}
}
/* out put->
The Window 1 is show!
The Window 3 is show!
The House is show!
The Window 2 is show!
*/
②static的初始化
package cai.Init;
/**
* 类InitStatic中,Window的static对象定义是在非static之前当然也在constructor之前,
* 并且static的初始化仅仅只是一次,而非static当重复调用时被初始化多次,不论是非static还是
* static的初始化都需要激发该类的初始化,否则对象的初始化将永远不会得到执行,就向下面Table中的
* window d将永远不会执行一样
*/
class Window {
public Window(String i){
System.out.println("The Window "+i+" is show!") ;
}
}
class Table {
static Window d = new Window("d"); //never match
}
class House {
Window a = new Window("a"); //before static and constructor
static Window b = new Window("b");
public House() {
System.out.println("The House is show!") ;
}
static Window c = new Window("c");
}
public class InitStatic {
static House house = new House();
public static void main(String args[]) {
new House();
}
}
/*output
* The Window b is show!
The Window c is show!
The Window a is show!
The House is show!
The Window a is show!
The House is show!
*/
总结一下吧:
1.假设有个Dog类,即使构造器没有显示的说明为static的,它也是static的,所以在首次创建dog类对象或者加载dog类对象成员时,java解析器都要去定位Dog.class文件.
2.然后载入Dog.class对象,这将创建一个Class对象,所有的static成员将被加载,这也就是为什么static只被加载一次的原因.
3.当用new Dog()创建对象时将在堆中为该对象分配足够大的空间,并把该对象中的各种成员变量初始化,int 被初始化为0,boolean被初始化为false,而引用则被设置成为null,等等。
4.执行所有字段定义处的初始化动作,也就是在类中的各种成员定义.
5.最后执行构造函数,这或许会有继承关系所以将牵扯到一系列的调用动作。
③下面来看看一个较复杂点的例子,并和继承关联起来
package cai.Init;
/**
* 我们来仔细分析下面类的加载顺序,当编译器通过static main()函数加载InheritInit类时,首先会加载各种static成员
* 所以首先初始化f,在这过程中初始化了该类的display方法,但在同等条件下的show方法却为能被执行,
* 因为没有类或对象的任何调用,它虽然是static的但它也为能被初始化,同等条件下的String e也是这样,
* 因为没有生成任何对象所以它也未能得到初始化,好啦,下面来看看其它类的初始化工作,由于main方法中的new House()的
* 调用,使得House类被加载,在加载时发现House的父类为Window所以会先加载Window,这里的初始化工作和 InheritInit
* 中的相似,所以static成员被加载,执行①,然后会找到子类中的static成员执行②,
* 在所有的static被执行完后,初始化对象的成员变量,因为有继承的关系所以首先执行③,再初始化构造函数Window,
* 最后初始化④,再执行构造函数House
*/
class Window {
String d = display("d"); //③
public Window() {
System.out.println("The Window constrctor is called!");
}
static String display(String str) {
System.out.println("The "+str+" is called!") ;
return str; //没有实际作用,只是为了为static成员变量初始化时调用该方法提供方便
}
static String a = display("a"); //①
}
class House extends Window{
static String display(String str) {
System.out.println("The "+str+" is called!") ;
return str; //没有实际作用,只是为了为static成员变量初始化时调用该方法提供方便
}
static String b = display("b"); //②
String c = display("c"); //④
public House() {
System.out.println("The House constructor is called!");
}
}
public class InheritInit {
String e = display("e"); //没有构造函数的激发它将永远不被调用
public static void main(String[] args) {
new House();
}
static String display(String str) {
System.out.println("The "+str+" is called!") ;
return str; //没有实际作用,只是为了为static成员变量初始化时调用该方法提供方便
}
static String f = display("f");
static void Show() { //没有类或对象任何调用虽然是static的但它也为能被初始化
System.out.println("is show!");
}
}
/*output
* The f is called!
The a is called!
The b is called!
The d is called!
The Window constructor is called!
The c is called!
*/