1

我的程序

class Building {
Building() {
    System.out.print("b ");
}

Building(String name) {
    this();
    System.out.print("bn " + name);
}
};

public class House extends Building {
House() {
    System.out.print("h "); // this is line# 1
}

House(String name) {
    this(); // This is line#2
    System.out.print("hn " + name);
}

public static void main(String[] args) {
    new House("x ");
}
}

我们知道编译器会super()在子类的构造函数的第一行写一个调用。因此输出不应该是:

b(从编译器调用 super(),在第 2 行之前

b(再次从编译器对 super() 的书面调用,在第 1 行之前)

h hn x

但输出是

b h hn x

这是为什么?

4

5 回答 5

5

当构造函数以调用另一个构造函数(thissuper)开始时,编译器不会插入对超类的默认构造函数的调用。因此,调用树是:

main
 \-> House(String)                (explicit call)
      |-> House()                 (explicit call)
      |    |-> Building()         (implicit call)
      |    |    |-> Object()      (implicit call)
      |    |    \-> print "b "
      |    \-> print "h "
      \-> print "hn x"
于 2012-12-19T16:58:45.890 回答
3

根据JLS 8.8.7

如果构造函数体不是以显式构造函数 调用开始并且被声明的构造函数不是原始类 Object 的一部分,则构造函数体隐式以超类构造函数调用“super();”开始

于 2012-12-19T17:01:31.223 回答
1

您的House(string name)构造函数调用House(),而后者又调用Building(). Building(string name)永远不会被调用。

如果你想显式调用Building(string name),在你的House(string name)构造函数中你可以添加这个:super(name);而不是this();

于 2012-12-19T17:00:46.737 回答
1

这是您的代码的可视化控制流程:

new House("x ")---> House(args)---> House() --->Building()--->Object()
                               ^^this()    ^implicit      ^implicit super() call 
                                             super()
                                             call

---> 代表调用

输出: b(from building no-args), h(from no-args House), hn x (from args House) bh hn x

据我所知,对 super 的隐式调用应该在 this() 之前,对吧?第 2 行,在我的代码中

编辑:

构造函数中的第一行是使用 super() 调用超类构造函数或使用 this() 调用重载构造函数。如果使用 this() 调用重载构造函数,则不会调用 super()。

于 2012-12-19T17:01:54.260 回答
0
House(x) -> House() + "hn" + "x"
            Building() + "h" + "hn" +"x"
            "b" + "h" + "hn" + "x"

对超类的调用只会被调用一次。

如果你想Building(string name)被调用,你必须明确地调用它。

我认为您使用它可能更容易,super()而不是this()

于 2012-12-19T17:02:36.180 回答