20

只是想知道像这样编译代码的原因:

class MyClass extends AnotherClass {
  {
    MySecondClass object = new MySecondClass();
    object.doSomething();
  }
}

这段代码和构造函数中的代码有什么区别?此代码在对象创建之前执行。

4

3 回答 3

23

大括号内没有名称的代码将成为类的构造函数的一部分,并在类构造函数中包含的逻辑之前执行。

快速示例:

public class Foo {
    {
        System.out.println("Before Foo()");
    }

    public Foo() {
        System.out.println("Inside Foo()");
    }

    {
        System.out.println("Not After Foo()");
    }
}
于 2013-06-08T15:36:55.953 回答
13

这称为实例初始化程序。初始化器中的代码插入到调用超类构造函数之后和构造函数其余代码之前。

任何构造函数的第一个操作都是调用超类构造函数。如果显式调用super(...)构造函数,则使用指定的构造函数。如果没有显式调用构造函数,则在超类中调用默认构造函数(不带参数)。如果不存在这样的构造函数,则为编译时错误。

在此显式或隐式构造函数调用之后,实例初始化程序按照它们在源代码中出现的顺序被调用(是的,您可以有多个初始化程序)。

为了说明,运行这个程序打印

另一个构造函数
初始化 1
初始化 2
测试构造函数
class Another {
  Another() { System.out.println("Another constructor"); }
}

class Test extends Another {

  public static void main(String[] args) { new Test(); }

  { System.out.println("Init 1"); }

  Test() { System.out.println("Test constructor"); }

  { System.out.println("Init 2"); }

}

最常见的应用程序是在初始化中的“双括号初始化”习语,其中定义了一个匿名内部类,并立即创建和配置了一个实例。这是 Swing 编程中一个相当常见的示例:

JButton popupButton = new JButton(new AbstractAction("Popup") {
  {
    putValue(Action.SHORT_DESCRIPTION, "Popup a dialog");
  }

  @Override
  public void actionPerformed(ActionEvent evt)
  {
    popup();
  }
});

如果您有多个构造函数,并且需要在每个构造函数中执行一些无参数初始化,这可能很有用。这可以被考虑到初始化块中。

于 2013-06-08T16:06:58.820 回答
3

这是一个构造函数之前运行的实例初始化块,如果你问为什么要使用它来代替构造函数?答案是否定的,你没有。

只是想知道像这样编译代码的原因:

在使用构造函数重载时,您通常使用它来分解公共代码。因此,上面的“ the ”实际上是指在公共实例初始化代码块执行后在对象实例化时调用的重载构造函数之一。

顺便说一句,您有时可以通过从另一个构造函数调用一个构造函数来实现相同的目的,但是调用必须在调用构造函数的第一行,否则代码将无法编译。

于 2013-06-08T15:47:02.203 回答