java编译器如何在继承中选择正确的方法和变量 [英] How does java compiler choose correct methods and variables in inheritance

查看:284
本文介绍了java编译器如何在继承中选择正确的方法和变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am a bit confused when inheritance and type casting is mixed. I want to understand the rules which java compiler follows when choosing correct methods and variables in inheritance.

我已经读过类似


变量在编译时被绑定,

Variables are bound at compile time and methods are bound at run time.

第二个来自 stackoverflow (@John Skeet)

The second one is from stackoverflow (@John Skeet)


过载解析基于方法目标和参数表达式的编译时类型确定在编译时确定的方法签名()

Overload resolution (which method signature is called) is determined at compile-time, based on the compile-time types of both the method target and the argument expressions

覆盖)是基于执行时目标对象的实际类型。

The implementation of that method signature (overriding) is based on the actual type of the target object at execution time.

但是问题是,解释具体情况,不考虑其他因素(如异常处理)时应遵循的一般过程。

But the problem is that they are explanations of specific situations and do not give the general process to be followed when other factors (like exception handling) are taken into consideration.

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

This may be bad practice but assume that both methods and variables are overridden(hidden in case of static variables).

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

Now if java compiler has to choose at compile time which method/variable needs to be invoked then what algorithm will it follow? Similarly at run time what is the algorithm that java compiler will use(based on the actual type of the object whose reference is being used)?

推荐答案

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

All method signatures and variables are verified during compile-time but the actual method calls are done / resolved during run-time.

例如:

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(); ,在编译期间,编译器只检查是否为类A(lhs引用)定义了 doSomething()。即使该方法不存在于 B 中,程序也将编译得很好。

Now, when you call a.doSomething(); , during compilation, the compiler just checks whether doSomething() is defined for class A (lhs reference). It is not even bothered about whether the method is also defined for class B. Even if the method were not present in B, the program would compile fine.

接下来,在运行时,JVM根据Object的类型( B )动态决定调用哪个方法。

Next, during runtime, the JVM dynamically decides which method to call based on type of Object (B in your case.).

因此,打印了in B

现在,回到田地。在编译期间解析对字段的访问。因此,如果字段在编译期不存在,那么编译失败。基于引用类型调用字段。因此, ai 将打印 5 A's code> i ),因为字段在编译期已解决。因此,区别在于,方法调用在运行期间被解析,在编译时期间它们的签名是需要/检查的,因为在编译期间检查/解析字段。

Now, coming back to fields. Access to fields are resolved during compile time. So, if a field doesn't exist during compile-time, then the compilation fails. The fields are called based on the reference type. So, a.i will print 5 (A's value of i) because the field was resolved during compile-time. Thus, the difference is, method calls are resolved during runtime, their signatures are needed / checked during compile-time where-as fields are checked / resolved during compile-time.

这篇关于java编译器如何在继承中选择正确的方法和变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆