简体   繁体   English

super() 是否在编译时运行而 this() 在运行时运行? 为什么?

[英]Does super() run in compiletime and this() run in runtime? and why?

in this program it will print "Student 1 Person 1 Undergrad 2 "在此程序中,它将打印“Student 1 Person 1 Undergrad 2”

that means super.method1() > super() of student this.method2() this of Undergrad()这意味着 super.method1() > super() of student this.method2() this of Undergrad()

Does super() run in compiletime and this() run in runtime? super() 是否在编译时运行而 this() 在运行时运行? and why?为什么?

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();    
        
    }

}

I expect output: It will cause an infinite execution, printing "Student 1" over and over.我期望输出:它将导致无限执行,一遍又一遍地打印“Student 1”。

output was:"Student 1 Person 1 Undergrad 2 ".输出为:“Student 1 Person 1 Undergrad 2”。

You are correct in that super.xxx() vs this.xxx() has some sort of a "compile time vs runtime" distinction, but it is certainly not that super.xxx() is " run " at compile time.您是正确的,因为super.xxx()this.xxx()具有某种“编译时与运行时”的区别,但肯定不是super.xxx()在编译时“运行”。

A more accurate wording would be, the method that will be called by a super.xxx call is decided at compile time ( statically dispatched ).更准确的措辞是, super.xxx调用将调用的方法是在编译时决定的(静态调度)。 And the method that will be called by a this.xxx call is decided at runtime ( dynamically dispatched ). this.xxx调用将调用的方法是在运行时决定的(动态调度)。

You can see this by comparing the clauses in the Java Language Specification, in the sections about processing method invocations.您可以通过比较 Java 语言规范中有关处理方法调用的部分中的条款来了解这一点。 The important steps that differs between super.xxx and this.xxx are (emphasis mine): super.xxxthis.xxx之间的重要区别是(强调我的):

Compile-Time Step 1: Determine Type to Search 编译时步骤 1:确定要搜索的类型

If the form is Primary. [TypeArguments] Identifier如果表格是Primary. [TypeArguments] Identifier Primary. [TypeArguments] Identifier , then let T be the type of the Primary expression. Primary. [TypeArguments] Identifier ,然后让 T 成为主表达式的类型。 The type to search is T if T is a class or interface type, or the upper bound of T if T is a type variable.如果 T 是类或接口类型,则要搜索的类型是 T;如果 T 是类型变量,则搜索的是 T 的上限。

If the form is super. [TypeArguments] Identifier如果表格是super. [TypeArguments] Identifier super. [TypeArguments] Identifier , then the type to search is the direct superclass type of the class whose declaration contains the method invocation . super. [TypeArguments] Identifier ,则要搜索的类型是声明包含方法调用的类的直接超类类型。

Notice that this is done at compile time.请注意,这是在编译时完成的。 The call super.method1();调用super.method1(); in Student will cause a search in Person because Person is "the class whose declaration contains the method invocation". in Student将导致在Person中进行搜索,因为Person是“其声明包含方法调用的类”。 Eventually, we'll find Person.method1 in a later step.最终,我们将在后面的步骤中找到Person.method1

On the other hand, the call this.method2();另一方面,调用this.method2(); in Student will search in Student . in Student将在Student中搜索。

Locate Method to Invoke 找到要调用的方法

  • Let Q be the qualifying class or interface of the method invocation (§13.1).Q为方法调用的限定类或接口(§13.1)。

  • Let m be the method found in Q or a superclass or superinterface of Q. (Note that m was merely the name of the method in the previous section; here it is the actual declaration.)m是在 Q 或 Q 的超类或超接口中找到的方法。(请注意,m 只是上一节中方法的名称;此处是实际声明。)

  • Let C be the class or interface that declares m.C为声明 m 的类或接口。

[...] [...]

  • If the invocation mode is super , overriding is not allowed.如果调用模式是super ,则不允许覆盖。 Method m of class or interface C is the one to be invoked.类或接口 C 的方法 m 是要调用的方法。 If m is abstract, an AbstractMethodError is thrown.如果 m 是抽象的,则抛出 AbstractMethodError。

[...] [...]

  • Otherwise, the invocation mode is interface or virtual .否则,调用模式是interfacevirtual

    If the method m of class or interface C is private, then it is the method to be invoked.如果类或接口 C 的方法 m 是私有的,则它是要调用的方法。

    Otherwise, overriding may occur.否则,可能会发生覆盖。 A dynamic method lookup, specified below, is used to locate the method to invoke.下面指定的动态方法查找用于定位要调用的方法。 The lookup procedure starts from class R, the actual run-time class of the target object.查找过程从类 R 开始,它是目标对象的实际运行时类。

This is a runtime step.这是一个运行时步骤。 For super.method1();对于super.method1(); , C is Person (since we found Person.method1() ), and the invocation mode is super , so that is what is invoked. , CPerson (因为我们找到Person.method1() ),调用方式是super ,所以调用的就是这个。

For this.method2();对于this.method2(); , a dynamic method lookup occurs, which in this case involves finding the appropriate overridden method depending on the runtime type of this . ,会发生动态方法查找,在本例中涉及根据this的运行时类型查找适当的重写方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM