为什么在我说 new House("x ") 时会调用超类构造函数 Building()?
Why superclass constructor Building() is invoked when I say new House("x ")?
我有以下代码,但我不明白为什么当我 运行 它在打印 "h hn x"
之前打印 "b"
。为什么 "b"
会被打印出来,因为我在执行 House()
时根本没有调用超类 Building
。
class Building {
Building() {
System.out.print("b ");
}
Building(String name) {
this();
System.out.println("bn " + name);
}
}
public class House extends Building {
House() {
System.out.println("h ");
}
House(String name) {
this();
System.out.println("hn " + name);
}
public static void main(String[] args) {
new House("x ");
}
}
超类的零参数构造函数由其子类的构造函数自动隐式调用。
更一般地说,对于
class B extends A
构造函数
public B()
{
//Your code
}
实际上看起来像
public B()
{
super(); //Call the superclass constructor
//Your code
}
您可以通过 显式 调用某些其他超类构造函数来覆盖此行为。请注意,如果无法对构造函数进行隐式调用(例如,如果您的无参数构造函数不存在),那么您将看到一个错误。
每当构造子类时,总是会调用超类构造函数。如果超类构造函数不需要任何参数,就像这里的情况一样,则可以隐式进行此调用。
如果您要在 Building 的构造函数中引入参数,您会在 House 中遇到错误,因为它需要您显式调用新的超类构造函数。
在继承中,有必要首先初始化 super-class 中存在的所有字段,因为这些字段在 subclasses 中使用,为此在构造你的 subclass super class 构造函数被调用以初始化 super class.
中存在的所有字段
构造子class实例时调用超级class构造函数。在您的代码中,您正在创建 new House("x ");
House
的实例。
它调用 House
参数化构造函数 House(String name)
此时你的超级 class 隐式构造函数被调用。
官方资源:
来自 Oracle javase 教程:
With super()
, the superclass no-argument constructor is called. With
super(parameter list)
, the superclass constructor with a matching
parameter list is called. Note: If a constructor does not explicitly
invoke a superclass constructor, the Java compiler automatically
inserts a call to the no-argument constructor of the superclass. If
the super class does not have a no-argument constructor, you will get
a compile-time error. Object
does have such a constructor, so if
Object
is the only superclass, there is no problem.
If a subclass constructor invokes a constructor of its superclass,
either explicitly or implicitly, you might think that there will be a
whole chain of constructors called, all the way back to the
constructor of Object
. In fact, this is the case. It is called
constructor chaining, and you need to be aware of it when there is a
long line of class descent.
额外资源:
SCJP 6 书中的构造函数链接部分以简单的方式清楚地解释了您要寻找的内容,它还提供了有关此过程的更多信息:
We know that constructors are invoked at runtime when you say new on
some class type as follows: Horse h = new Horse();
But what really
happens when you say new Horse()
? (Assume Horse extends Animal
and
Animal extends Object
.)
Horse
constructor is invoked. Every constructor invokes the constructor of its superclass with an (implicit) call to super()
,
unless the constructor invokes an overloaded constructor of the same
class (more on that in a minute).
Animal
constructor is invoked (Animal
is the superclass of Horse
).
Object
constructor is invoked (Object
is the ultimate superclass of all classes, so class Animal
extends Object
even though you don't
actually type "extends Object"
into the Animal
class declaration. It's
implicit.) At this point we're on the top of the stack.
Object
instance variables are given their explicit values. By explicit values, we mean values that are assigned at the time the
variables are declared, like "int x = 27"
, where "27"
is the explicit
value (as opposed to the default value) of the instance variable.
Object
constructor completes.
Animal
instance variables are given their explicit values (if any).
Animal
constructor completes.
Horse
instance variables are given their explicit values (if any).
Horse
constructor completes.
类比你的例子:
所以当您说 new House("x ")
时,会发生以下情况:
House(String name)
按照关键字 this()
的指定调用 House()
。
House()
构造函数隐式调用 super()
,后者调用构造函数 Building()
。
Building()
构造函数隐式调用 super()
,即 Object
构造函数。
Object
构造函数完成
Building()
构造函数将完成并打印 "b "
House()
构造函数将完成并打印 "h"
House(String name)
构造函数将完成并打印 "hn x "
。
- 结果是
"b h hn x "
注意: Building(String name)
如果您添加了从 House()
到 super("someString")
的显式调用,将被调用,在这种情况下,结果将是:"b bn someString h hn x "
如果您单步执行程序,调用堆栈会显示正在发生的事情:
(需要从下往上看调用栈):
House(Building).<init>() line: 3
House.<init>() line: 2
House.<init>(String) line: 7
House.main(String[]) line: 12
- 第一个 Main 被称为
- 然后在 House(name) 构造函数中调用 this()
- 这会调用 House() 构造函数(因为没有提供参数)
- 有趣的部分来了:因为调用了默认构造函数并且 House 派生自 Building,因此需要首先构造 Building,根据规范它是父 class Building 的默认构造函数。
我有以下代码,但我不明白为什么当我 运行 它在打印 "h hn x"
之前打印 "b"
。为什么 "b"
会被打印出来,因为我在执行 House()
时根本没有调用超类 Building
。
class Building {
Building() {
System.out.print("b ");
}
Building(String name) {
this();
System.out.println("bn " + name);
}
}
public class House extends Building {
House() {
System.out.println("h ");
}
House(String name) {
this();
System.out.println("hn " + name);
}
public static void main(String[] args) {
new House("x ");
}
}
超类的零参数构造函数由其子类的构造函数自动隐式调用。
更一般地说,对于
class B extends A
构造函数
public B()
{
//Your code
}
实际上看起来像
public B()
{
super(); //Call the superclass constructor
//Your code
}
您可以通过 显式 调用某些其他超类构造函数来覆盖此行为。请注意,如果无法对构造函数进行隐式调用(例如,如果您的无参数构造函数不存在),那么您将看到一个错误。
每当构造子类时,总是会调用超类构造函数。如果超类构造函数不需要任何参数,就像这里的情况一样,则可以隐式进行此调用。
如果您要在 Building 的构造函数中引入参数,您会在 House 中遇到错误,因为它需要您显式调用新的超类构造函数。
在继承中,有必要首先初始化 super-class 中存在的所有字段,因为这些字段在 subclasses 中使用,为此在构造你的 subclass super class 构造函数被调用以初始化 super class.
中存在的所有字段构造子class实例时调用超级class构造函数。在您的代码中,您正在创建 new House("x ");
House
的实例。
它调用 House
参数化构造函数 House(String name)
此时你的超级 class 隐式构造函数被调用。
官方资源:
来自 Oracle javase 教程:
With
super()
, the superclass no-argument constructor is called. Withsuper(parameter list)
, the superclass constructor with a matching parameter list is called. Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error.Object
does have such a constructor, so ifObject
is the only superclass, there is no problem.If a subclass constructor invokes a constructor of its superclass, either explicitly or implicitly, you might think that there will be a whole chain of constructors called, all the way back to the constructor of
Object
. In fact, this is the case. It is called constructor chaining, and you need to be aware of it when there is a long line of class descent.
额外资源:
SCJP 6 书中的构造函数链接部分以简单的方式清楚地解释了您要寻找的内容,它还提供了有关此过程的更多信息:
We know that constructors are invoked at runtime when you say new on some class type as follows:
Horse h = new Horse();
But what really happens when you saynew Horse()
? (AssumeHorse extends Animal
andAnimal extends Object
.)
Horse
constructor is invoked. Every constructor invokes the constructor of its superclass with an (implicit) call tosuper()
, unless the constructor invokes an overloaded constructor of the same class (more on that in a minute).Animal
constructor is invoked (Animal
is the superclass ofHorse
).Object
constructor is invoked (Object
is the ultimate superclass of all classes, so classAnimal
extendsObject
even though you don't actually type"extends Object"
into theAnimal
class declaration. It's implicit.) At this point we're on the top of the stack.Object
instance variables are given their explicit values. By explicit values, we mean values that are assigned at the time the variables are declared, like"int x = 27"
, where"27"
is the explicit value (as opposed to the default value) of the instance variable.Object
constructor completes.Animal
instance variables are given their explicit values (if any).Animal
constructor completes.Horse
instance variables are given their explicit values (if any).Horse
constructor completes.
类比你的例子:
所以当您说 new House("x ")
时,会发生以下情况:
House(String name)
按照关键字this()
的指定调用House()
。House()
构造函数隐式调用super()
,后者调用构造函数Building()
。Building()
构造函数隐式调用super()
,即Object
构造函数。Object
构造函数完成Building()
构造函数将完成并打印"b "
House()
构造函数将完成并打印"h"
House(String name)
构造函数将完成并打印"hn x "
。- 结果是
"b h hn x "
注意: Building(String name)
如果您添加了从 House()
到 super("someString")
的显式调用,将被调用,在这种情况下,结果将是:"b bn someString h hn x "
如果您单步执行程序,调用堆栈会显示正在发生的事情:
(需要从下往上看调用栈):
House(Building).<init>() line: 3
House.<init>() line: 2
House.<init>(String) line: 7
House.main(String[]) line: 12
- 第一个 Main 被称为
- 然后在 House(name) 构造函数中调用 this()
- 这会调用 House() 构造函数(因为没有提供参数)
- 有趣的部分来了:因为调用了默认构造函数并且 House 派生自 Building,因此需要首先构造 Building,根据规范它是父 class Building 的默认构造函数。