关于java中重载和类型提升的理论探讨

Abd*_*del 7 java overloading type-promotion

如果有两个方法,如add(int,long)add(long,int),这样的通话add(10,10)将被视为不确定性.

但是,如果我们有这样的例子,为什么它仍然被认为是歧义?

static void add(short num1, short num2) {
    System.out.println("add(short, short)");
}

static void add(byte num1, long num2) {
    System.out.println("add(byte, long)");
}

public static void main(String[] args) {
    byte num1 = 10;
    byte num2 = 10;

    add(num1, num2);
}
Run Code Online (Sandbox Code Playgroud)

我想知道编译器如何确定它是模棱两可的?虽然(在我看来)它不应该因为add(short, short)需要两个类型的促销步骤,并add(byte, long)需要三个类型的促销..或者我有一个误解?

use*_*740 3

8.4.9。重载 -\n来自 Java 语言规范“重载解析过程” - 特别是15.12.2.5。选择最具体的方法

\n
\n

如果多个成员方法既可访问又适用于方法调用,则需要选择一个成员方法来为运行时方法分派提供描述符。Java 编程语言使用选择最具体方法的规则。

\n

..

\n

对于使用参数表达式 e1, ..., ek 的调用,如果满足以下任一条件,则一个适用的方法 m1比另一适用的方法 m2具体:

\n
    \n
  • [..]

    \n
  • \n
  • m2 不是泛型,m1 和 m2 可通过严格或松散调用应用,其中 m1 具有形式参数类型 S1, ..., Sn,m2 具有形式参数类型 T1, ..., Tn,类型 Si 更重要对于所有 i (1 \xe2\x89\xa4 i \xe2\x89\xa4 n, n = k) ,参数 ei 比 Ti 更具体

    \n
  • \n
  • [..]

    \n
  • \n
\n

..

\n

可能没有一种方法是最具体的,因为有两种或多种方法是最具体的..[有更多关于具体/抽象的规则..]

\n

否则,方法调用不明确,并且会发生编译时错误。

\n
\n

Java 编译器只是遵循这些规则;不同的语言将遵循不同的规则,并且人们在决定选择哪个重载时可能会发明自己的非 Java 规则。

\n
\n

要选择更具体的方法,它必须对所有参数都更具体。因此,示例案例在调用时会导致不明确的调用add(byte,byte),因为:

\n
    \n
  • add(short num1 /* less specific */, short num2 /* MORE specific */)
  • \n
  • add(byte num1 /* MORE specific */, long num2 /* less specific */)
  • \n
\n

但是,如果add(byte num1, long num2)更改为add(byte num1, short num2)它将编译,因为:

\n
    \n
  • add(short num1 /* less specific */, short num2 /* as specific */)
  • \n
  • add(byte num1 /* MORE specific */, short num2 /* as specific */)
  • \n
\n

原语之间的关系见4.10.1。原始类型之间的子类型:long>int>short>byte:

\n

  • 天哪,那套规则太复杂了,所以我用“..这里有很多规则..”来打赌,这并不能令人满意地显示 Java 编译器所采取的确切过程。 (2认同)
  • 哎呀,我有机会提炼相关规则和选择过程。YMMV 和 tldr;这就是 Java 的工作原理。 (2认同)