首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java显式构造函数调用&实例初始化器

Java显式构造函数调用&实例初始化器
EN

Stack Overflow用户
提问于 2012-09-03 20:32:43
回答 3查看 10.2K关注 0票数 4

在Java教程- 初始化字段中,对实例初始化块(实例初始化程序)进行了描述:

编译器将初始化程序块复制到每个构造函数中。因此,这种方法可以用于在多个构造函数之间共享代码块。

如果转述是正确的,则对下列代码:

代码语言:javascript
运行
复制
public class ConstructorTest {

    public static void main(String[] args) {
        Child c = new Child();
    }
}

class Parent {
    Parent() {
        System.out.println("Parent non-argument Constructor");
    }
}

class Child extends Parent {

    {
        System.out.println("Child Instance Initialization Block");
    }

    Child() {
        this(2);
        System.out.println("Child no-argument Constructor");

    }

    Child(int i) {
        this(10, i);
        System.out.println("Child 1-argument Constructor");
    }

    Child(int i, int j) {
        System.out.println("Child 2-argument Constructor");
    }
}

产出应是:

代码语言:javascript
运行
复制
Parent non-parm Constructor
Child Instance Initialization Block
Child 2-argument Constructor
Child Instance Initialization Block
Child 1-argument Constructor
Child Instance Initialization Block
Child no-argument Constructor

但实际产出是:

代码语言:javascript
运行
复制
Parent non-argument Constructor
Child Instance Initialization Block
Child 2-argument Constructor
Child 1-argument Constructor
Child no-argument Constructor

我被误解了那句话的意思,还是描述不够准确?

对于显式构造函数调用的另一个疑问是:

根据两个基本概念:

  • 如果存在,则另一个构造函数的调用必须是构造函数中的第一行。
  • 在构造函数中,使用this()调用另一个构造函数,使用super()调用直接超类的相应构造函数。

这是否意味着在子类的构造函数中使用this()将隐式删除对超类的无参数构造函数的默认调用?

谢谢你的回复。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-03 20:38:53

编辑:事实证明JLS是准确的,尽管它很难读懂。这一切在第12.5条中都很详细

在作为结果返回对新创建对象的引用之前,将使用以下过程处理指示的构造函数以初始化新对象:

  1. 将构造函数的参数分配给此构造函数调用的新创建的参数变量。
  2. 如果该构造函数以同一个类中的另一个构造函数的显式构造函数调用(§8.8.7.1)开始(使用此方法),则使用这五个步骤递归地计算参数和处理构造函数调用。如果构造函数调用突然完成,则此过程出于同样的原因突然完成;否则,继续执行步骤5
  3. 此构造函数不以同一类中的另一个构造函数的显式构造函数调用开始(使用此方法)。如果此构造函数用于对象以外的类,则此构造函数将以超类构造函数的显式或隐式调用(使用超级)开始。使用这五个步骤递归地评估超类构造函数调用的参数和过程。如果构造函数调用突然完成,则此过程出于同样的原因突然完成。否则,继续执行步骤4。
  4. 为该类执行实例初始化器和实例变量初始化器,将实例变量初始化器的值按从左到右的顺序分配给相应的实例变量,这些变量在类的源代码中以文本形式出现。如果执行这些初始化程序中的任何一个都会导致异常,那么将不再处理其他初始化器,并且该过程在相同的异常下突然完成。否则,继续执行步骤5。
  5. 执行此构造函数主体的其余部分。如果该执行突然完成,则此过程出于同样的原因突然完成。否则,此过程将正常完成。

注意突出显示的部分--执行链式构造函数,然后跳过步骤4,它将执行实例初始化程序。

实际上,实例和字段初始化程序只执行一次,从输出中可以看出这一点。

非正式地说,我认为将这一程序描述为:

  • 继续在同一个类(this(...))中链接构造函数,直到到达不以this开头的构造函数体为止。
  • 执行适当的超级构造函数。
  • 执行实例变量初始化器和实例初始化器。
  • 执行“最内部”构造函数的主体
  • 继续弹出构造函数体的堆栈,直到最终得到"entry“构造函数为止。

这是否意味着在子类的构造函数中使用this()将隐式删除对超类的无参数构造函数的默认调用?

是。在类的构造函数链中的某个位置,可以保证最终得到一个构造函数,该构造函数可以隐式或显式地调用super。这是唯一被调用的超类构造函数。

编辑:注意,您引用的教程显然是不正确的。

样本类:

代码语言:javascript
运行
复制
public class Test {
    {
        System.out.println("Foo");
    }
    
    public Test() {
    }
    
    public Test(int i)  {
        this();
    }
}

来自javap -c的输出

代码语言:javascript
运行
复制
public class Test {
  public Test();
    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 Foo
       9: invokevirtual #4  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      12: return

  public Test(int);
    Code:
       0: aload_0
       1: invokespecial #5                  // Method "<init>":()V
       4: return
}

如您所见,Test(int)的构造函数没有编译实例构造函数的代码。

基本上,只有直接调用超类构造函数的构造函数具有复制到它们中的实例初始化程序代码。当然,所有其他构造函数都将导致通过调用超类构造函数的构造函数执行实例初始化程序代码。

票数 5
EN

Stack Overflow用户

发布于 2012-09-03 20:38:21

初始化块在实例化类的对象时只运行一次(使用任何构造函数<=,这是您的疑问)。当类加载器加载类时,静态初始化块只运行一次。

这是否意味着在子类的构造函数中使用this()将隐式删除对超类的无参数构造函数的默认调用?

不是的。这个()将调用同一个类的另一个构造函数,在本例中是默认构造函数(如果存在的话)。此构造函数(默认构造函数)将调用super()。

票数 0
EN

Stack Overflow用户

发布于 2012-09-03 20:53:21

我认为Java语言规范更准确:http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.6

类中声明的实例初始化器在创建类的实例时执行。

http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.5步骤4和5中,请描述您观察到的输出:

4.执行这个类的实例初始化器和实例变量初始化器. 5.执行这个构造函数主体的其余部分.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12253712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档