实例初始化器和构造函数之间有什么区别?

时间:2013-06-08 15:35:54

标签: java

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

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

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

3 个答案:

答案 0 :(得分:23)

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

快速举例:

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

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

    {
        System.out.println("Not After Foo()");
    }
}

答案 1 :(得分:13)

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

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

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

为了说明,运行此程序打印

Another constructor
Init 1
Init 2
Test constructor
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"); }

}

最常见的应用程序是"double brace initialization" idiom,初始化,其中定义了一个匿名内部类,并且一次创建并配置了一个实例。这是Swing编程中一个相当常见的例子:

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

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

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

答案 2 :(得分:3)

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

  

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

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

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