0

我不知道这个问题之前是否被问过。我搜索但找不到任何重复的问题。如果您发现任何相关问题,请提及链接。

public class Exp 
{
    Exp()
    {
         System.out.println("Hello");      //3
    }
    {    System.out.println("Hello")};    //1
    {    static{System.out.print("x");}   //2
}

消息的打印顺序是 2,1,3。

这些第 1 行和第 2 行的意义是什么以及为什么执行命令

4

4 回答 4

3

第“1”行是一个实例初始化程序,它在第一次创建对象时运行,在调用任何构造函数之前。

第“2”行是一个静态初始化程序,它在第一次加载类时运行,在创建任何对象之前。

JLS 的第 12.5 节规定了实例初始化程序何时运行:

就在作为结果返回对新创建对象的引用之前,使用以下过程处理指示的构造函数以初始化新对象:

将构造函数的参数分配给此构造函数调用的新创建的参数变量。

如果此构造函数以同一类中另一个构造函数的显式构造函数调用(第 8.8.7.1 节)开始(使用 this),则评估参数并使用这五个相同的步骤递归地处理该构造函数调用。如果该构造函数调用突然完成,则此过程出于相同原因而突然完成;否则,继续执行步骤 5。

此构造函数不以显式构造函数调用同一类中的另一个构造函数开始(使用 this)。如果此构造函数用于 Object 以外的类,则此构造函数将以显式或隐式调用超类构造函数(使用 super)开始。使用这五个相同的步骤递归地评估超类构造函数调用的参数和过程。如果该构造函数调用突然完成,则此过程出于相同的原因突然完成。否则,继续执行步骤 4。

执行该类的实例初始化程序和实例变量初始化程序,将实例变量初始化程序的值分配给相应的实例变量,按照它们在源代码中以文本形式出现的从左到右的顺序。如果执行这些初始化程序中的任何一个导致异常,则不会处理更多初始化程序,并且此过程会突然完成相同的异常。否则,继续执行步骤 5。

执行此构造函数的其余部分。如果该执行突然完成,则此过程出于同样的原因突然完成。否则,此过程正常完成。

(强调我的)

构造函数主体的其余部分在实例初始化程序之后执行。

于 2013-10-22T19:36:21.507 回答
1

类的静态块在类加载期间与常量(静态最终成员)一起执行。3 在实例化对象时调用。让您更好地理解调试代码,通过您的 IDE 了解执行顺序。

于 2013-10-22T19:36:01.827 回答
1

请参阅http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html

静态初始化块是用大括号 { } 括起来并以 static 关键字开头的普通代码块。这是一个例子:

static {
    // whatever code is needed for initialization goes here
}

一个类可以有任意数量的静态初始化块,它们可以出现在类主体的任何位置。运行时系统保证静态初始化块按照它们在源代码中出现的顺序被调用。

于 2013-10-22T19:37:23.317 回答
0

执行顺序的原因是,在非静态块中您可能想要使用静态成员,但在静态块中您不能使用非静态成员。所以先执行静态块是有意义的。非静态块允许您抽象每个构造函数需要执行的代码,因此它会在构造函数之前执行。

更详细的执行顺序:

1.超类的静态块

2.这个类的静态块

3.超类的非静态块

4.超类的构造函数

5.该类的非静态块

6.这个类的构造函数

于 2013-10-22T19:40:15.180 回答