我想了解this example from Thinking in Java:
package c07;
import com.bruceeckel.simpletest.*;
class Meal {
Meal() { System.out.println("Meal()"); }
}
class Bread {
Bread() { System.out.println("Bread()"); }
}
class Cheese {
Cheese() { System.out.println("Cheese()"); }
}
class Lettuce {
Lettuce() { System.out.println("Lettuce()"); }
}
class Lunch extends Meal {
Lunch() { System.out.println("Lunch()"); }
}
class PortableLunch extends Lunch {
PortableLunch() { System.out.println("PortableLunch()");}
}
public class Sandwich extends PortableLunch {
private static Test monitor = new Test();
private Bread b = new Bread();
private Cheese c = new Cheese();
private Lettuce l = new Lettuce();
public Sandwich() {
System.out.println("Sandwich()");
}
public static void main(String[] args) {
new Sandwich();
monitor.expect(new String[] {
"Meal()",
"Lunch()",
"PortableLunch()",
"Bread()",
"Cheese()",
"Lettuce()",
"Sandwich()"
});
}
}
据我从Java语言规范中了解,执行顺序从加载包含main方法的类开始。然后必须初始化此类的所有静态和成员变量(在此之前必须初始化超类的所有成员变量,尽管在这种情况下没有这些变量)。
所以我认为b
,c
,l
会在main
开始执行之前初始化。但是,输出似乎并非如此。我错过了什么吗?
答案 0 :(得分:5)
不,b
和c
是实例变量。
没有包含main
的类的自动实例化。仅初始化 static 变量。这就好像一些外部来电者写道:
Sandwich.main(args);
所以当你写道:
然后必须初始化此类的所有静态和成员变量
......那是错的。只初始化静态变量 - 正常情况。
答案 1 :(得分:0)
示例输出正确。以下是重要规则:
创建类时,必须首先调用超类的构造函数。这冒泡到Object
类
在调用构造函数之前,调用成员变量初始化。
此示例中不涉及static
,但技术monitor
除外。
答案 2 :(得分:0)
JLS # 12.4.1. When Initialization Occurs
类或接口类型T将在第一次出现以下任何一个之前立即初始化:
JLS # 12.5. Creation of New Class Instances
每当创建一个新的类实例时,为它分配内存空间,为类类型中声明的所有实例变量提供空间,并在类类型的每个超类中声明所有实例变量,包括可能的所有实例变量隐藏(§8.3)。