【问题标题】:How non-static initializer block invoked? [closed]如何调用非静态初始化程序块? [关闭]
【发布时间】:2013-12-15 10:42:04
【问题描述】:
public class A{

    {
        System.out.println("hi i am IIB");
    }

    public A(){
        System.out.println("hi i am constructor");
    }

    public static void main(String... args){
        A objA=new A();
    }

}

【问题讨论】:

  • 你有什么问题?
  • 当我创建一个对象时,iib会在构造函数被调用之前执行,所以谁来调用iib
  • 请在您的问题中添加您的评论,例如“当我创建一个对象时,iib 将在调用构造函数之前执行,因此谁将调用 iib”,这样会更清楚。好的代码示例顺便说一句

标签: java initialization initializer non-static


【解决方案1】:

iib 将在构造函数被调用之前执行

不,这不是发生的事情。 实例初始化块中编写的代码仅在运行时是构造函数的一部分。在编译时,编译器将 instance initializer blocks 的代码移动到类的所有构造函数中。因此,在运行时,构造函数实际上等效于:

public A() {
    super();
    System.out.println("hi i am IIB"); 
    System.out.println("hi i am constructor");
}

因此,实例初始化块中的语句被移动到构造函数之前已经存在的语句。

这是构造函数的实际样子(javap 命令的输出):

 public A();
   Code:
      0: aload_0
      1: invokespecial #1    // Method java/lang/Object."<init>":()V
      4: getstatic     #2    // Field java/lang/System.out:Ljava/io/PrintStream;
      7: ldc           #3    // String hi i am IIB
      9: invokevirtual #4    // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     12: getstatic     #2    // Field java/lang/System.out:Ljava/io/PrintStream;
     15: ldc           #5    // String hi i am constructor
     17: invokevirtual #4    // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     20: return

【讨论】:

    【解决方案2】:

    Java Language Specification 定义了调用构造函数时执行的内容:

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

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

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

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

    【讨论】:

      【解决方案3】:

      没有人会显式调用 IIB,而是将 IIB 复制到每个构造函数中(在您的情况下,紧接在隐式 super() 之后)。考虑添加第二个构造函数,如下所示,

      public A(int arg){
          super();
          // Here is where the IIB will be copied.
          System.out.println("hi i am constructor 2");
      }
      
      public static void main(String... args) {
        A obj = new A();
        A objA = new A(2); // call the second constructor.
      }
      

      哪个会输出 -

      hi i am IIB
      hi i am constructor
      hi i am IIB
      hi i am constructor 2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-26
        • 1970-01-01
        • 2015-05-24
        • 2011-01-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多