提问人:ahmed alaa 提问时间:12/17/2022 更新时间:12/17/2022 访问量:82
super() 是否在编译时运行,this() 在运行时运行?为什么?
Does super() run in compiletime and this() run in runtime? and why?
问:
在这个程序中,它将打印“学生 1 人 1 本科生 2 ”
这意味着 Student 的 super.method1() > super() this.method2() 本科生的这个
super() 是否在编译时运行,this() 在运行时运行?为什么 ?
public class Person {
public void method1() {
System.out.print("Person 1 ");
}
public void method2() {
System.out.print("Person 2 ");
}
}
public class Student extends Person {
public void method1() {
System.out.print("Student 1 ");
super.method1();
this.method2();
}
public void method2() {
System.out.print("Student 2 ");
}
}
public class Undergrad extends Student {
/*public void method1() {
System.out.print("ahmed");
}*/
public void method2() {
System.out.print("Undergrad 2 ");
}
}
public class main {
static void main(){
Person u = new Undergrad();
u.method1();
}
}
我期望输出:它会导致无限执行,一遍又一遍地打印“学生 1”。
输出为:“学生 1 人 1 本科生 2”。
答:
你是对的,因为 vs 有某种“编译时与运行时”的区别,但肯定不是在编译时“运行”。super.xxx()
this.xxx()
super.xxx()
更准确的措辞是,调用将调用的方法在编译时决定(静态调度)。调用将调用的方法在运行时决定(动态调度)。super.xxx
this.xxx
您可以通过比较 Java 语言规范中有关处理方法调用的部分中的子句来了解这一点。和 之间不同的重要步骤是(强调我的):super.xxx
this.xxx
编译时步骤 1:确定要搜索的类型
如果形式是 ,则设 T 为主表达式的类型。如果 T 是类或接口类型,则要搜索的类型为 T,如果 T 是类型变量,则搜索的类型为 T 的上限。
Primary . [TypeArguments] Identifier
如果形式是 ,则要搜索的类型是其声明包含方法调用的类的直接超类类型。
super . [TypeArguments] Identifier
请注意,这是在编译时完成的。调用将导致搜索,因为是“其声明包含方法调用的类”。最终,我们将在后面的步骤中找到。super.method1();
Student
Person
Person
Person.method1
另一方面,呼入将搜索 .this.method2();
Student
Student
找到要调用的方法
设为方法调用的限定类或接口 (§13.1)。
Q
假设是 Q 中的方法或 Q 的超类或超接口(请注意,m 只是前面方法的名称 部分;这是实际的声明。
m
设为声明 m 的类或接口。
C
[...]
- 如果调用模式为
super
,则不允许覆盖。类或接口 C 的方法 m 是要调用的方法。如果 m 是抽象的, 抛出 AbstractMethodError。[...]
否则,调用模式为 或 。
interface
virtual
如果类或接口 C 的方法 m 是私有的,则它是要调用的方法。
否则,可能会发生覆盖。下面指定的动态方法查找用于查找要调用的方法。查找 过程从类 R(目标的实际运行时类)开始 对象。
这是一个运行时步骤。对于 ,是(因为我们找到了 ),而调用模式是 ,所以这就是调用的内容。super.method1();
C
Person
Person.method1()
super
对于 ,将进行动态方法查找,在本例中,这涉及根据 的运行时类型查找适当的被覆盖方法。this.method2();
this
评论