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

Old*_*kon 20 java

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

class MyClass extends AnotherClass {
  {
    MySecondClass object = new MySecondClass();
    object.doSomething();
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Lui*_*oza 23

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

快速举例:

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

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

    {
        System.out.println("Not After Foo()");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它在每个构造函数之前.(`javap -c`会告诉你.) (5认同)

eri*_*son 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"); }

}
Run Code Online (Sandbox Code Playgroud)

最常见的应用程序是initalization中的"双括号初始化"习惯用法,其中定义了匿名内部类,并且一次创建和配置实例.这是Swing编程中一个相当常见的例子:

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

  @Override
  public void actionPerformed(ActionEvent evt)
  {
    popup();
  }
});
Run Code Online (Sandbox Code Playgroud)

如果您有多个构造函数,并且需要在每个构造函数中执行一些无参数初始化,这可能很有用.这可以作为初始化块的因素.