对编译器处理继承和方法调用感到困惑
Confused about compiler handling inheritance and method invocation
在阅读了一些有关继承和方法调用以及编译器如何处理这些信息后,我感到很困惑。因此,如果有人能看看我是如何看待事物并纠正我错误的地方,我将不胜感激。
我们先来看看下面的代码:
Class答:
public class A {
public void testMethodA(String a) {
System.out.println(a);
}
}
Class乙:
public class B extends A {
}
主要
public class Main {
public static void main(String[] args) {
B b = new B();
b.testMethodA("test");
}
}
现在让我们看看我的理解方式(如有错误请指正):
- 在继承过程中,当创建子class对象时,您正在创建一个对象,该对象接收所有父class对象的所有字段和方法。所以subclasses的字段和方法在编译时不会从superclasses转移到subclasses(来源:Does an instance of superclass get created when we instantiate an object?)
- 在编译期间,编译器会检查所调用的支持参数类型的方法是否定义在声明的引用类型中。因此在示例中:
A a = new A(); a.testMethod("test")
它会在编译时检查 testMethod() 是否在 class A[=53= 中定义] 可以接收 String 作为参数。 (来源:How does java compiler choose correct methods and variables in inheritance)
- 当运行时发生时,testMethod() 从存储在变量 a 中的实际对象调用,这并不总是由于多态性 A 类型的对象。
现在实际问题:
根据我上面描述的逻辑和代码,我预计在编译期间会出现 Cannot resolve method 错误。原因是在编译期间,编译器会检查 class B 是否存在 testMethodA(String) 。然而,这是从 class A 继承的方法,据我所知,继承的方法不会传递给 subclasses,而是传递给 sub[=75 的对象=]es 在运行时。因此,如果 testMethodA(String) 在编译期间不存在于 class B 中,编译器如何仍能成功编译代码?它肯定不会检查方法的对象,因为尚未创建该对象。
这个问题没有在'possible answer'中回答,因为这个帖子是我在描述这个问题时自己标记为知识来源的帖子。
我想,你的主要误解在第2点。
During compile time, the compiler checks if the called to method that
supports the argument type is defined in the declared reference type.
这应该更好地阅读:
在编译期间,编译器检查被调用的支持参数类型的方法是否在声明的引用类型中定义或其超类型之一或沿整个树实现的接口.
编译器知道 B
的任何实例(作为 A
的子 class)都将有一个方法 testMethodA()
,或者是从 super 继承的方法class A
,或来自子class 的覆盖方法,因此调用该方法是安全的。
您使用措辞 "pass" 来描述字段和方法从 superclass 到 subclass 的继承。这个措辞对我来说听起来很混乱,因为它暗示了一些只发生部分的重复过程。对于实例字段,这或多或少是可以的,因为 subclass 的每个实例都将获得 superclass 字段加上 subclass 字段的单独副本。但是方法不会被复制到实例中,它们会保留 "in" 定义它们的 classes(如果添加方法,实例不会占用更多内存)。在内部,Java 运行时维护某种查找 table 来为给定实例的 class.
找到合适的方法版本
所以我认为"pass a method to the subclass object"的措辞与实际过程不符
在阅读了一些有关继承和方法调用以及编译器如何处理这些信息后,我感到很困惑。因此,如果有人能看看我是如何看待事物并纠正我错误的地方,我将不胜感激。
我们先来看看下面的代码:
Class答:
public class A {
public void testMethodA(String a) {
System.out.println(a);
}
}
Class乙:
public class B extends A {
}
主要
public class Main {
public static void main(String[] args) {
B b = new B();
b.testMethodA("test");
}
}
现在让我们看看我的理解方式(如有错误请指正):
- 在继承过程中,当创建子class对象时,您正在创建一个对象,该对象接收所有父class对象的所有字段和方法。所以subclasses的字段和方法在编译时不会从superclasses转移到subclasses(来源:Does an instance of superclass get created when we instantiate an object?)
- 在编译期间,编译器会检查所调用的支持参数类型的方法是否定义在声明的引用类型中。因此在示例中:
A a = new A(); a.testMethod("test")
它会在编译时检查 testMethod() 是否在 class A[=53= 中定义] 可以接收 String 作为参数。 (来源:How does java compiler choose correct methods and variables in inheritance) - 当运行时发生时,testMethod() 从存储在变量 a 中的实际对象调用,这并不总是由于多态性 A 类型的对象。
现在实际问题:
根据我上面描述的逻辑和代码,我预计在编译期间会出现 Cannot resolve method 错误。原因是在编译期间,编译器会检查 class B 是否存在 testMethodA(String) 。然而,这是从 class A 继承的方法,据我所知,继承的方法不会传递给 subclasses,而是传递给 sub[=75 的对象=]es 在运行时。因此,如果 testMethodA(String) 在编译期间不存在于 class B 中,编译器如何仍能成功编译代码?它肯定不会检查方法的对象,因为尚未创建该对象。
这个问题没有在'possible answer'中回答,因为这个帖子是我在描述这个问题时自己标记为知识来源的帖子。
我想,你的主要误解在第2点。
During compile time, the compiler checks if the called to method that supports the argument type is defined in the declared reference type.
这应该更好地阅读:
在编译期间,编译器检查被调用的支持参数类型的方法是否在声明的引用类型中定义或其超类型之一或沿整个树实现的接口.
编译器知道 B
的任何实例(作为 A
的子 class)都将有一个方法 testMethodA()
,或者是从 super 继承的方法class A
,或来自子class 的覆盖方法,因此调用该方法是安全的。
您使用措辞 "pass" 来描述字段和方法从 superclass 到 subclass 的继承。这个措辞对我来说听起来很混乱,因为它暗示了一些只发生部分的重复过程。对于实例字段,这或多或少是可以的,因为 subclass 的每个实例都将获得 superclass 字段加上 subclass 字段的单独副本。但是方法不会被复制到实例中,它们会保留 "in" 定义它们的 classes(如果添加方法,实例不会占用更多内存)。在内部,Java 运行时维护某种查找 table 来为给定实例的 class.
找到合适的方法版本所以我认为"pass a method to the subclass object"的措辞与实际过程不符