当从子类调用super()时,它会在'this'对象上调用,即由语句new Subclass()创建的对象。在'this'对象上调用super()。但'this'对象包含所有变量,超类的方法及其本身及其构造函数,但不包含超类构造函数。那么如何在'this'对象上调用super()?
请参阅附件中我试图解释我的理解。
注意:P是超类,Q是派生类
答案 0 :(得分:6)
但是'这个' object contains ...不是超类构造函数。
它包含"包含"超类构造函数(只要它"包含"任何方法,有点手工波浪) - 它只是唯一方式来调用超级构造函数是使用super(..)
语法及其约束(具体来说,它必须是子类的构造函数的第一个语句)。
在那挥手:一个物体实际上并没有包含一种方法。方法是在参数上调用的静态事物,当您调用this.foo()
时,它基本上被(由JVM)转换为foo(this)
。名称this
实际上只是&#34的特殊名称;该方法的第一个参数,恰好是我期望的this
。"
构造函数的工作方式完全相同。 new Foo()
分配一些内存,将其变量初始化为默认值(0 / null),然后调用Foo.<init>(<a reference to the new chunk of memory>)
。如果Foo构造函数调用super()
,则Foo.<init>
中的第一个语句基本上是FooSuperClass.<init>(this)
。
这不是Java语法的工作原理,但它基本上是在发生什么。
实际上,请查看这段Java代码:
// in Super.java
public class Super {}
// in Sub.java
public class Sub extends Super {}
如果你javap -c Sub
,你会看到:
Compiled from "Sub.java"
public class Sub extends Super {
public Sub();
Code:
0: aload_0
1: invokespecial #1 // Method Super."<init>":()V
4: return
}
这是做什么的?在0
它将第一个参数推送到Sub()
构造函数(又名this
)到堆栈,然后在1
它调用Super.<init>
,这将弹出参数并将其传递给Super.<init>
方法。 (最后,在4
返回。)
答案 1 :(得分:3)
'this'对象确实包含超类构造函数。
因为Q
是P
的子类(或派生类),Q
可以访问相同的方法,字段和构造函数确实。就super()
的实例而言,Q
构造函数将构造P
的实例。在使用super()
之后,必须进行任何其他初始化。请注意,super()
必须是构造函数中的第一行,如果您要使用它。
public Q()
{
super();
//other TO-DO...
}
答案 2 :(得分:2)
在java中,只要实例化子类,就会隐式调用其超类构造函数。这是因为,父类需要首先进行初始化,以确保派生类具有所有这些值。
答案 3 :(得分:2)
始终定义默认构造函数(即没有参数的构造函数)。
您不必为您的班级提供任何构造函数,但在执行此操作时必须小心。编译器自动为没有构造函数的任何类提供无参数的默认构造函数。此默认构造函数将调用超类的无参数构造函数。在这种情况下,如果超类没有无参数构造函数,编译器会抱怨,因此您必须验证它是否存在。如果你的类没有显式的超类,那么它有一个隐式的超类Object,它有一个无参数的构造函数。
请参阅:https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
此构造函数将始终被隐式调用,但您也可以显式调用它。
如果你向P添加一个构造函数P(String foo, int bar)
,你将不得不在Q中调用该构造函数:
public class Q {
public Q() {
super("answer", 42);
}
}