首先,给出一句话:
#######java尽力保证:所有变量在使用前都能得到恰当的初始化。
成员初始化:
1、对于方法内部的局部变量而言,在未初始化之前就进行调用,那么编译器就会报错。
2、对于类的基本类型数据成员而言,即使未显式初始化,那么编译器也会自动予以初始化。
public class InitialTest {
int i ;
double d;
int increase(){
int i =0;
i++;
this.i ++;
this.i ++;
System.out.println(i);
return this.i;
}
InitialTest inc(){
i++;
d++;
return this;
}
}
假如此时在InitialTest内main方法调用increase方法,是完全可行的,此时类的两个成员变量会按以下进行初始化:
int i =0;
double d=0d;
如果是包含引用类型,如定义:
public class Initial{
Object object;
}
那么此时object则会被初始化成null。
构造器初始化:
先看如下代码:
public class ConstructorInitial{
int i;
ConstructorInitial(){
i = 1;
}
}
那么编译器在给i分配内存时,则自动将i对应的存储空间的值初始化成0.然后在调用的时候才被构造器初始化成1.
即使写成以下形式,也是按照上述流程,会初始化两次。
public class ConstructorInitial{
int i=1;
}
原因:编译器的自动初始化,在对对象实例化之前就已执行。
静态数据成员的初始化:
class Bowl {
Bowl(int marker) {
print("Bowl(" + marker + ")");
}
void f1(int marker) {
print("f1(" + marker + ")");
}
}
class Table {
static Bowl bowl1 = new Bowl(1);
Table() {
print("Table()");
bowl2.f1(1);
}
void f2(int marker) {
print("f2(" + marker + ")");
}
static Bowl bowl2 = new Bowl(2);
}
class Cupboard {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard() {
print("Cupboard()");
bowl4.f1(2);
}
void f3(int marker) {
print("f3(" + marker + ")");
}
static Bowl bowl5 = new Bowl(5);
}
public class StaticInitialization {
public static void main(String[] args) {
print("Creating new Cupboard() in main");
new Cupboard();
print("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1);
}
static Table table = new Table();
static Cupboard cupboard = new Cupboard();
}
第一次写这个demo,最基本的原则不知道,错的牛头不对马嘴。看了一下之后,就ok了。把我理解的初始化写一下:
1、优先级:静态成员变量>非静态成员变量>构造器;
2、同类型的成员变量按定义的先后顺序进行初始化;
3、静态成员变量在初始化一次之后,再下一次调用时,则不会再初始化;
4、若当前类拥有父类时,则优先初始化父类成员变量;
有这4条,再写上面demo的结果就比较简单了。
关于静态成员的初始化,还有一种情况,就是静态代码块。其实把由static包起来的部分看做是一个静态成员就好了,当其中任意一个成员面临初始化的时候,其中所有的静态成员会按照static代码块内初始化的顺序逐个初始化。
参考: java编程思想(thinking in java 4 edition,初始化与顺序章节)。