5

JVM如何选择执行哪个方法?

选择过程是否分为两部分。首先在编译 JVM 时寻找一个候选方法来执行。它将所需的签名选择到声明的对象类中(不是有效的)。一旦它选择了候选签名,它就会从对象的有效类开始在层次结构中寻找它。
这个对吗?

还有一个问题:

这是一个类层次结构和相关方法:

- Class A: +f(short x): int; +f(String x): int;
- Class B extends A: +f(int x): int; +f(String x): int;
- Class C extends A: +f(double x): int; +f(byte x): int;
- Class D extends C: +f(byte x): int; +f(short x): int;
- Class E extends C: +f(char x): int; +f(int x): int;

所以:

  • A 是 B 和 C 的超类
  • B 是 A 的子类
  • C 是 A 的子类
  • C 是 D 和 E 的超类
  • D 和 E 是 C 子类

所有这些类都只有一个名为“f”的方法,带有提到的签名。

我现在声明以下对象:

A a = new D();
B b = new B();
C c = new E();

1、为什么方法调用af(3)不能处理并返回错误?

如果我之前提到的是正确的,这就是应该发生的:

JVM 在 A 类中查找带有签名 f(int x) 或任何兼容签名(带有强制转换)的方法。它找到了应该兼容的方法 f(short x),对吧?然后它在 D 类中寻找这个非常精确的签名,并发现它正在执行 D:f(short x)。根据我的书,这是不正确的,为什么?可能是因为 short 实际上并不是对 int 的提升,因此 JVM 不认为 f(short x) 适合调用?因此找不到任何兼容的 f 方法并会返回错误。

我检查了谷歌和我能找到的任何其他资源(也在 Stackoverflow 上),但都非常明显且没有足够详细的答案,因此我认为问这个问题可能是件好事,我希望它会让我们知道答案是对于未来与超载和压倒一切作战的学生很有用:) 在此先感谢。

4

2 回答 2

1

The only two methods that could be called are:

Class A: +f(short x): int; +f(String x): int;

In order for the cast to be valid we need to implicitly cast the integer 3 to either a short or a string.

But you cannot implicitly convert the integer 3 to the smaller size short. And of course it can't be implicitly cast to a string so it can't be handled.

Edit:

Because you put an instance of class D into the A container, the instance a only knows about A methods. You have to cast the instance of a to D in order to call D's methods which then would enable you to implicitly cast the int 3 to a double and call the f(double) method.

于 2013-07-12T22:00:44.490 回答
-2

关于你的第二个问题(为什么方法调用错误)

您已经将自己置于需要担心的四个复杂事情的位置:重载、覆盖、数据类型转换和(可能)自动装箱。

最有趣的可能实际上是转换。http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

由于继承规则,对象a有以下操作:

 f(byte) (from D)
 f(short) (from D)
 f(double) (from C)
 f(String) (from A)

但问题是,用值 3 调用这个函数实际上意味着“一个整数常量 3”。您不能将整数隐式转换为字节或字符串,因为这是一种缩小转换。但是,您可以将整数隐式转换为双精度或浮点数。

所以我希望 af(3) 从 C 中评估 f(double)。

于 2013-07-12T22:07:08.257 回答