在阅读了有关继承和方法调用以及编译器如何处理这些信息之后,我感到困惑。因此,如果有人看看我如何看待事物并在错误的地方纠正我,我将不胜感激。
首先让我们看一下以下代码:
A级
public class A {
public void testMethodA(String a) {
System.out.println(a);
}
}
B类:
public class B extends A {
}
主要
public class Main {
public static void main(String[] args) {
B b = new B();
b.testMethodA("test");
}
}
现在让我们看一下我对事物的理解方式(如果我错了,请纠正我):
A a = new A(); a.testMethod("test")
将在编译期间检查是否在类 A 中定义了 testMethod(),该类可以接收 String < / strong>作为参数。 (来源:How does java compiler choose correct methods and variables in inheritance)现在是实际问题:
根据上述逻辑和代码,我预计在编译期间会出现无法解析方法错误。原因是在编译期间,编译器检查 B 类是否存在 testMethodA(String)。但是,此方法是从 A 类继承的,并且据我了解,继承的方法不会在运行时传递给子类,而是传递给子类的对象。因此,如果在编译期间 B 类中不存在 testMethodA(String),那么编译器又如何才能成功地编译代码?当然,它不会检查该方法的对象,因为尚未创建该对象。
此问题未在“可能的答案”中回答,因为该线程是我自己在描述此问题时标记为知识来源的线程。
答案 0 :(得分:1)
我认为,您的主要误解在于第2点。
在编译期间,编译器检查被调用的方法是否 支持在声明的引用类型中定义的参数类型。
最好阅读:
在编译期间,编译器会检查是否在声明的引用类型中定义了支持参数类型的被调用方法或其沿整个树的超类型之一或已实现的接口。
编译器知道B
的任何实例(是A
的子类)将具有方法testMethodA()
,该方法可以是从超类A
继承的方法,也可以是子类中重写的一个,因此可以安全地调用该方法。
您使用“ pass”一词来描述字段和方法从超类到子类的继承。这个措辞听起来让我感到困惑,因为它暗示了某些重复过程,而该过程只是部分发生。对于实例字段,这或多或少是可以的,因为子类的每个实例都将获得超类字段和子类字段的单独副本。但是方法不会被复制到实例,它们会“保留”在定义它们的类中(如果添加方法,实例不会占用更多内存)。在内部,Java Runtime维护某种查找表,以查找给定实例类的适当方法版本。
因此,我认为“将方法传递给子类对象”这一措词与实际过程不符。