Java尽力保证:所有变量在使用前都能得到恰当的初始化。对于局部变量,Java以编译时错误的形式来贯彻这种保证。
public static void main(String[] args) {
int i;
System.out.println(i++);
}
运行结果:
Error:(12, 28) java: 可能尚未初始化变量i
类的没有基本数据成员保证都会有一个初始值,即使数据成员并未显示赋初值。对于类中的对象引用来说,如果不将其初始化,此引用就会获得一个特殊值null。
public class Dog {
public String name;
public int age;
public Dog son;
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(dog.name);
System.out.println(++dog.age);
System.out.println(dog.son);
}
}
运行结果:
null
1
null
如果我们在定义类成员变量时没有为其定义初值,那么编译器就会自动为其加上初值。boolean为false,short、int、long为0,float、double为0.0,char为0所以显示为空。
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
public class Window {
public Window(){
System.out.println("Window()");
}
}
public class House {
public Window win = new Window();
public House(){
System.out.println("House()");
}
}
public class Test {
public static void main(String[] args) {
House h = new House();
}
}
运行结果:
Window()
House()
从上例中可以看到,成员变量初始化先于构造方法运行。那么,对于静态成员来说,情况是否一样呢?来看看下面例子。
public class Bowl {
Bowl(int marker){
System.out.println("Bowl(" + marker + ")");
}
void f1(int marker){
System.out.println("f1(" + marker + ")");
}
}
public class Table {
static Bowl bowl1 = new Bowl(1);
Table(){
System.out.println("Table()");
bowl2.f1(1);
}
void f2(int marker){
System.out.println("f2(" + marker + ")");
}
static Bowl bowl2 = new Bowl(2);
}
public class Cupboard {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard(){
System.out.println("Cupboard()");
bowl4.f1(2);
}
void f3(int marker){
System.out.println("f3(" + marker + ")");
}
static Bowl bowl5 = new Bowl(5);
}
public class Test {
public static void main(String[] args) {
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1);
}
static Table table = new Table();
static Cupboard cupboard = new Cupboard();
}
运行结果:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)
初始化顺序是先初始化静态对象(如果它们因前面的对象创建过程而被初始化),而后是非静态对象
如果大家知道这一点,上面输出结果就不难解释了——Test类中,先初始化table,进入table类中先有静态属性bowl1,再进入Bowl类中,发现没有成员变量,直接调用Bowl的构造方法,输出Bowl(1)。再回到Table类中,再有静态属性bowl2,同理输出Bowl(2)。然后调用Table类的构造方法,输出Table()、f1(1),此时Test类中的静态属性table初始化完成,再根据相同的原则初始化cupboard。**不过这里值得注意的是,静态属性只会初始化一次。**最后执行main()方法里的内容。
最后,我们来总结一下对象的创建过程,假设有个名为Dog的类:
- 即使没有显式地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog地对象时,或者Dog类地静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。
- 然后载入Dog.class,有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
- 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
- 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值,而引用则被设置成了null。
5、执行所有出现于字段定义处的初始化动作。
6、执行构造器。
1476

被折叠的 条评论
为什么被折叠?



