如何调用非静态初始化程序块?

时间:2013-12-15 10:42:05

标签: java initialization initializer non-static

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();
    }

}

3 个答案:

答案 0 :(得分:6)

  

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

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

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

答案 1 :(得分:3)

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

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

  2. 如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7.1节)开头(使用此方法),则使用这五个相同步骤计算参数并以递归方式处理该构造函数调用。如果该构造函数调用突然完成,则此过程突然完成,原因相同;否则,继续步骤5.

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

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

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

答案 2 :(得分:1)

没有人会明确地调用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