小编典典

Java编译器如何在继承中选择正确的方法和变量

java

当继承与类型转换混合在一起时,我有点困惑。我想了解在继承中选择正确的方法和变量时java编译器遵循的规则。

我读过类似的东西

变量在编译时绑定,方法在运行时绑定。

重载分辨率 (称为方法签名)是在编译时根据方法目标和参数表达式的编译时类型确定的

该方法签名( 覆盖 )的实现基于执行时目标对象的实际类型。

但是问题在于它们只是对特定情况的解释,没有考虑其他因素(例如异常处理)时要遵循的一般过程。

这可能是不好的作法,但假设方法和变量都被覆盖(在static变量的情况下被隐藏)。

现在,如果Java编译器必须在编译时选择需要调用哪种方法/变量,那么它将遵循哪种算法?同样,在运行时,java编译器将使用什么算法(基于正在使用其引用的对象的实际类型)?


阅读 243

收藏
2020-11-30

共1个答案

小编典典

所有方法签名和变量都在编译时进行验证,但实际的方法调用在运行时完成/解析。

例如 :

class A {
int i=5;
public void doSomething(){
//print "in A"
}
}

class B extends A{
int i=10;    
public void doSomething(){
// print "in B"
}

public static void main(String[] args){
A a = new B();
a.doSomething();
}
}

现在,当您调用时a.doSomething();,在编译过程中,编译器仅检查是否doSomething()为类A定义了(lhs参考)。甚至不必担心是否也为类B定义了该方法。即使该方法不存在B,该程序也可以正常编译。

接下来,在运行时,JVM根据对象的类型(B根据您的情况)动态决定要调用的方法。

因此,"in B"被打印。

现在,回到领域。在编译期间将解决对字段的访问。因此,如果在编译期间不存在任何字段,则编译将失败。这些字段根据引用类型进行调用。因此,a.i将打印5A'si),因为该字段在编译时已解决。因此,不同之处在于,方法调用在运行时解析,在编译时需要/检查其签名,而在编译时则检查/解析字段。

2020-11-30