Java如何确定隐式类型调用调用哪种方法?

tor*_*tal 4 java methods type-conversion

当我和我的朋友们为考试而学习时,这个问题就出现了.调用静态赋值变量的方法时,我们注意到了奇怪的行为.

代码>单词所以我们走了:

class C {

    public void a(double x) {}
}

class D extends C {
    void b() {} 
}

class F extends D {

    void a(int i) {} 
    void a(double d) {} 
Run Code Online (Sandbox Code Playgroud)

现在,做

D foo = new F();
foo.a(1);
Run Code Online (Sandbox Code Playgroud)

这会给什么?嗯..它在F中运行方法a(双)!

这就是我们想到的事情:

  1. 计划通过寻找开始一个静态类型d什么也没有.
  2. 去超级班,C.找不到(int)而是找到(double).
  3. 决定这是我的意思(即一个(双)),但是FIIRST,在所有这些搜索之后让我们首先看一下动态类型!
  4. 在F中运行一个(双)!

它是否正确?这意味着它爬上层次结构以找到一些方法,如果从int到double的类型转换完成,它可以适合.在此之后它检查动态类型是否具有这个新解释的签名.

我注意到,如果我加入

void a(int) {}
Run Code Online (Sandbox Code Playgroud)

**在C类中,当运行上面的调用时,它会在F中给我一个(int)!

有人可以解释一下这个过程中涉及的机制吗?为什么代码以这种方式运行/编译?这背后的技术原因是什么?还有更多关于类似情况应该注意的事情()

Ant*_*ony 7

原因是Java是静态类型的.参数类型的调度是在编译时完成的,而不是运行时.

编译代码时,编译器会发现您正在调用a在静态类型的对象上命名的方法D.它寻找兼容的方法D,并找到一个方法(继承自C).它生成代码以执行虚拟调用C.a(double).

在运行时,虚拟调用调度对象的实际类型(而不是参数!),因此它最终会调用F.a(double),因为这会覆盖C.a(double).

事件的运行时类型是F并且F恰好具有在编译时已知的有效的不同方法这一事实是无关紧要的.如果您想要这种行为,则需要反思.

如果添加C.a(int),编译器会看到两种不同的方法命名aD,并根据超载规则,选择一个接受一个int.