Java如何通过隐式类型调用确定要调用的方法?

Java如何通过隐式类型调用确定要调用的方法?,java,methods,type-conversion,Java,Methods,Type Conversion,这个问题是在我和我的朋友们准备考试时出现的。调用静态赋值变量的方法时,我们注意到了奇怪的行为 代码>文字,我们开始: 现在,做什么 D foo = new F(); foo.a(1); 这会带来什么?好。。它在F中运行方法a(双) 这就是我们认为发生的事情: 程序首先在静态类型D中查找a:无任何内容 转到它的超级类,C。不查找a(int),而是查找a(double) 决定这是我想要的签名(即a(double)),但首先,在所有这些搜索之后,让我们先看看它所说的动态类型 在F中运行a(双) 这是

这个问题是在我和我的朋友们准备考试时出现的。调用静态赋值变量的方法时,我们注意到了奇怪的行为

代码>文字,我们开始:

现在,做什么

D foo = new F();
foo.a(1);
这会带来什么?好。。它在F中运行方法a(双)

这就是我们认为发生的事情:

  • 程序首先在静态类型D中查找a:无任何内容
  • 转到它的超级类,C。不查找a(int),而是查找a(double)
  • 决定这是我想要的签名(即a(double)),但首先,在所有这些搜索之后,让我们先看看它所说的动态类型
  • 在F中运行a(双) 这是正确的吗?这意味着,如果完成了从int到double的类型转换,它会爬过层次结构来找到一些适合的方法。。然后检查动态类型是否有这个新解释的签名

    我注意到如果我加上

    void a(int) {}
    
    **在类C中,当运行上面的调用时,它会在F中给我a(int)


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

    原因是Java是静态类型的。参数类型的分派是在编译时完成的,而不是在运行时

    编译代码时,编译器会看到您正在对静态类型为
    D
    的对象调用名为
    a
    的方法。它在
    D
    中查找兼容的方法,并找到一个方法(继承自
    C
    )。它生成代码来执行对
    C.a(double)
    的虚拟调用

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

    对象的运行时类型是
    F
    ,而
    F
    恰好有一个不同的方法,如果在编译时已知该方法,则该方法是有效的,这一事实与此无关。如果你想要这种行为,你需要反思


    如果添加了
    C.a(int)
    ,编译器将在
    D
    中看到两个名为
    a
    的不同方法,并根据重载规则,选择一个接受int的方法。

    要调用的方法在编译时解析,而不是在运行时解析。由于编译器只在编译时知道foo是一个
    D
    ,因此只有一个方法
    a(double)
    ,这就是调用的方法。但是,要调用的对象的
    a(double)
    是动态的(在运行时),这就是为什么要调用
    F.a(double)
    ,而不是
    C.a(double)

    这称为单分派:要调用的方法在其被调用的对象上是动态的,但在其参数类型上是静态的


    如果你在
    C
    中完全删除了该方法,它就不会在
    F
    中调用
    a(int)
    ,它只会编译失败,说它找不到该方法。

    哇,答案太好了!我现在将深入探讨这一点!
    void a(int) {}