在java编程语言中,所有变量在使用之前都必须尽量保证得到了合理的初始化,对于函数中的局部变量则以编译时的错误来提醒数据没有初始化。比如:
void f()
{
Int j;
j++;//此处会给出一个编译错误:j没有初始化
}
然而,若类的数据成员是基本类型,则每个基本类型数据成员都会得到一个初始值;在类中定义一个对象引用时,如果没有对其进行初始化,则系统会给一个特殊值null对其进行初始化。
一、构造器初始化
当想为变量付初值时,可以在类成员变量定义的时候为其赋值,也可以调用某个函数方法来进行初始化,通常调用构造函数来进行初始化。但是,自动初始化将在构造器被调用之前进行,是不可阻止的。比如:
Public class Constructor
{
Int j;
Constructor(){j=10;}
}
其中,j首先会被置0进行自动初始化,而后调用默认构造函数进行初始化为10;由此,编译器不会硬性要求在构造函数中或者使用之前对元素进行初始化,因为初始化已经自动完成了。
二、初始化顺序
在类的内部,变量的定义顺序就是其初始化的顺序,且这些变量一定会在所有方法(包括构造函数)被调用之前得到合理的初始化。比如:
// InitOrder.java
Class Window
{
Window(int mark){System.out.println(“Window(”+ mark+”)”);}
}
Class House
{
Window w1=new Window(1);
House()
{
System.out.println(“House()”);
Window w3=new Window(33);
}
Window w2= new Window(2);
Void f()
{
System.out.println(“f()”);
}
Window w3=new Window(3);
}
Public class InitOrder
{
Public static void main(Strng[ ] args)
{
House h=new House();
h.f();
}
}
[分析]:
[1].在主函数中,定义了一个类House的对象h,而House中又包含了Window类。因此,House类中的所有变量会在所有函数调用之前按照定义的先后顺序进行初始化,即初始化顺序为w1->w2->w3->House()->w33。
[2].每个变量类型有一个不可阻止的自动初始化过程,而后才是程序员进行指定的初始化过程。在这里,类House中的Window是定义的一个对象引用,因此自动初始化就是赋予初值null。
基于上述分析,该代码段的运行结果应为:
Window(1)
Window(2)
Window(3)
House();
Window(33)
f()
三、静态数据的初始化
静态数据只有在必要的时候才会进行初始化过程,如果包含静态数据的类不被创建,则静态数据至始至终都不会被创建,也就不会被初始化;当类对象被创建或者是静态数据第一次被访问时,他们才会被初始化,此后,静态对象不会被再次初始化。
另外,当一个类中同时包含静态与非静态数据时,初始化的顺序是先静态、后非静态。比如:
// StaticInitlizition.java
Class Bowl
{
Bowl(int mark){System.out.println(“Bowl(”+mark+”)”);}
Void f1(int mark){ System.out.println(“f1(”+mark+”)”);}
}
Class Table
{
Static Bowl bowl1=new Bowl(1);
Table()
{
System.out.println(“Table()”);
Bowl2.f1(1);
}
Void f2(int mark)
{
System.out.println(“f2(”+mark+”)”);
}
Static Bowl bowl2=new Bowl(2);
}
Class Cupboard
{
Bowl bowl3=new Bowl(3);
Static Bowl bowl4=new Bowl(4);
Cupboard()
{
Bowl(int mark){System.out.println(“Cupboard()”);}
bowl4.f1(2);
}
Void f3(int mark)
{
System.out.println(“f3(”+mark+”)”);
}
Static Bowl bowl5=new Bowl(5);
}
Public class StaticInitlizition
{
Public static void main(String[ ] args)
{
System.out.println(“creat new Cupboard() in main ”);
New Cupboard();
System.out.println(“creat new Cupboard() in main ”);
New Cupboard();
Tab.f2(1);
Cup.f3(1);
}
Static Table Tab=new Table();
Static Cupboard Cup=new Cupboard ();
}
[分析]:
[1].主函数中,所有的类对象或者变量将在所有的函数调用之前被初始化;此处,相同类型的变量按先后顺序进行初始化。即先初始化Tab后Cup;再调用其他函数。
[2].在类Table中,定义有两个static Bowl对象,一个Bowl对象,初始化时按先static后非static的顺序进行,而后调用默认构造函数Table()进行初始化。
[3].在类Cupboard中,同理先static后非static的顺序进行,再是默认构造函数Cupboard();
[4]。很重要的一点:static对象在第一次初始化以后,当第二次再遇到时将不再进行初始化了。
基于上述分析,本代码段运行后的结果应该是:
//static Table Tab=new Table()
Bowl(1)
Bowl(2)
Table()
f1(1)
// Static Cupboard Cup=new Cupboard ()
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
//此时,static对象将不会再次被初始化
creat new Cupboard() in main
// New Cupboard()
Bowl(3)
Cupboard()
f1(2)
//此时,static对象将不会再次被初始化
creat new Cupboard() in main
// New Cupboard()
Bowl(3)
Cupboard()
f1(2)
// Tab.f2(1)
f2(1)
// Cup.f3(1)
f3(1)
Refrence: Bruce Eckel <<Thinking In Java>>Fourth Edition