Java中的执行顺序

时间:2012-10-02 18:36:25

标签: java order-of-execution

我想了解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方法的类开始。然后必须初始化此类的所有静态和成员变量(在此之前必须初始化超类的所有成员变量,尽管在这种情况下没有这些变量)。

所以我认为bcl会在main开始执行之前初始化。但是,输出似乎并非如此。我错过了什么吗?

3 个答案:

答案 0 :(得分:5)

不,bc实例变量。

没有包含main的类的自动实例化。仅初始化 static 变量。这就好像一些外部来电者写道:

Sandwich.main(args);

所以当你写道:

  

然后必须初始化此类的所有静态和成员变量

......那是错的。只初始化静态变量 - 正常情况。

答案 1 :(得分:0)

示例输出正确。以下是重要规则:

  • 创建类时,必须首先调用超类的构造函数。这冒泡到Object

  • 在调用构造函数之前,调用成员变量初始化。

此示例中不涉及static,但技术monitor除外。

答案 2 :(得分:0)

JLS # 12.4.1. When Initialization Occurs

类或接口类型T将在第一次出现以下任何一个之前立即初始化:

  • T是一个类,创建了一个T实例。
  • T是一个类,调用T声明的静态方法。
  • 分配由T声明的静态字段。
  • 使用由T声明的静态字段,该字段不是常量 变量(§4.12.4)。
  • T是顶级课程(第7.6节)和断言声明(第14.10节) 在词典中嵌套在T(§8.1.3)中执行。

JLS # 12.5. Creation of New Class Instances

  

每当创建一个新的类实例时,为它分配内存空间,为类类型中声明的所有实例变量提供空间,并在类类型的每个超类中声明所有实例变量,包括可能的所有实例变量隐藏(§8.3)。