静态初始化
当一个类的静态方法/静态域被首次访问时,该类被加载,此时静态初始化的所有动作被执行,静态初始化只在类对象首次加载的时候进行一次。
/* 该例子证明了静态域被首次访问时,该类被加载,静态初始化的动作被执行了,且只会进行一次,
非静态初始化的方法没有被执行。*/
class Dog{
static String className="dog";
static String name=setName();
String say=setSay();
static String setName(){
System.out.println("静态");
return "哈士奇";
}
String setSay(){
System.out.println("非静态");
return "汪汪汪";
}
Dog(){
System.out.println("Dog Constructor");
}
}
public class Initialize {
public static void main(String[] args) {
System.out.println(Dog.className);
System.out.println(Dog.name);
}
}
/* out
静态
dog
哈士奇
*/
非静态初始化
非静态初始化的动作在创建对象时(实例化)被执行。
1.new Dog()创建对象时,在堆上会为该对象分配足够的存储空间
2.这块存储空间被清零(初始化成二进制的零,即基本类型数据初始化为0,对象引用初始化成null)
3.开始执行非静态字段定义处的初始化动作
4.执行构造器
/* 可以看到,new Dog();创建对象时,静态初始化也执行了,因为构造器实际也是static方法,
只不过它的static关键字没有被显式的表达出来。
该例证明了创建对象时,类会先进行静态初始化动作,之后进行非静态初始化动作,最后执行构造器,
非静态初始化动作在每一次创建对象时都需要执行。
步骤2、3在后面证明。
*/
class Dog{
static String name=setName();
String say=setSay();
static String setName(){
System.out.println("静态");
return "哈士奇";
}
String setSay(){
System.out.println("非静态");
return "汪汪汪";
}
Dog(){
System.out.println("Dog Constructor");
}
}
public class Initialize {
public static void main(String[] args) {
new Dog();
new Dog();
}
}
/* out
静态
非静态
Dog Constructor
非静态
Dog Constructor
*/
涉及继承的初始化
- 在加载子类的过程中,编译器注意到它有一个基类(这是由关键字extends得知的),于是它继续进行加载(去加载基类)。不管你是否打算产生一个该基类的对象,这都要发生。
- 如果该基类还有其自身的基类,那么第二个基类就会被加载,如此类推。接下来根基类中的static初始化即会被执行,然后是下一个导出类,以此类推。
- 在所有静态字段初始化结束后,必要的类都已经加载完毕,对象就可以被创建了。首先,对象中所有的基本类型都会被设为默认值,对象引用被设为null——这是通过将对象内存设为二进制零值(上面说到的存储空间被清零)而一举生成的。
- 然后,从基类开始向下下执行,按照非静态字段初始化的顺序,先执行非静态初始化的动作,最后调用构造器,之后按这个顺序向下执行它的导出类,以此类推。
/*
该例证明了初始化的顺序:
1.先执行静态字段初始化的动作
2.在非静态字段初始化与构造器调用前,先给对象分配存储空间,并将存储空间清零(初始化成二进制的零),
所以可以看到Animal的构造器调用了被覆盖后的print()方法输出的结果是"dog.print(): 0" 而
不是 "dog.print(): 1"
3.在存储空间分配结束后,才从基类开始向下依次执行初始化,顺序为先执行非静态字段初始化,然后调用构
造器,然后向下初始化它的导出类,以此类推。
*/
class Animal{
static String animalName = setAnimalName();
void print(){
System.out.println("animal.print()");
}
static String setAnimalName(){
System.out.println("动物");
return "Animal";
}
Animal(){
print();
System.out.println("Animal Constructor");
}
}
class Mammalia extends Animal{
static private String mammaliaName=setMammaliaName();
private String mean=setMean();
static String setMammaliaName(){
System.out.println("哺乳动物");
return "Mammalia";
}
String setMean(){
System.out.println("母乳喂养");
return "母乳喂养";
}
Mammalia(){
System.out.println("Mammalia Constructor");
}
}
class Dog extends Mammalia{
int i=1;
static String name=setName();
String say=setSay();
@Override
void print() {
System.out.println("dog.print(): "+i);
}
static String setName(){
System.out.println("狗");
return "哈士奇";
}
String setSay(){
System.out.println("叫声");
return "汪汪汪";
}
Dog(){
System.out.println("Dog Constructor");
}
}
public class Initialize {
public static void main(String[] args) {
new Dog();
}
}
/* out
动物
哺乳动物
狗
dog.print(): 0
Animal Constructor
母乳喂养
Mammalia Constructor
叫声
Dog Constructor
*/