方法重载:单参数与交替参数

Method overloading : Single parameter vs alternating parameters

这个问题可能类似于Java overload confusion

我正在读一本书,其中有一个关于方法重载的主题,编译器可能无法从中解析被调用的方法。书中的例子使用了带有两个参数 (int, double)(double, int) 的重载方法。调用此方法如 overloadedTwoParam(4, 5) 将导致编译器错误,因为 int 可以传递给 double。我的问题是,如果我的参数只有一个,为什么编译器能够解析将调用哪个方法?

public class Test {

    public static void main(String[] args) {
        Test t = new Test();
        t.overloadedSingleParam(1); //this is working
        t.overloadedTwoParam(4, 5); //this is NOT working
    }

    void overloadedSingleParam(double a) {
        // do something here..
    }

    void overloadedSingleParam(int a) {
        // do something here..
    }

    void overloadedTwoParam(double a, int b) {
        // do something here..
    }

    void overloadedTwoParam(int a, double b) {
        // do something here..
    }
}

My question here is why compiler able to resolve which method will be called if my parameter is only one

当涉及到单个参数时,编译器能够看到有一个方法采用 int,因此不会混淆应该调用哪个方法。即使您删除采用单个 int 的方法,编译器仍将能够调用采用单个 double 的方法,因为这里没有歧义。 (int可以晋升为double)

当谈到交替使用 intdouble 参数的其他方法时,编译器不想负责决定是否将第一个参数提升为 doubledouble 的第二个参数。

CKing 的直觉和答案很好。
我将使用 JLS 参考来完成。

总体思路是:编译器选择最具体的方法...如果找到它

JLS 表示非正式的直觉是,如果第一个方法处理的任何调用可以传递给另一个方法而没有 compile-time 类型错误,则一个方法比另一个方法更具体. 是简版。
在引用的 JLS link 中,指定了编译器为选择最具体的方法而应用的所有规则。

可能没有一种方法是最具体的,因为有两种或多种方法是最具体的。在这种情况下,会发生编译错误,指出方法调用不明确。


在第一种情况下编译很好,因为你有一个独特的最大特定方法:

Test t = new Test();
t.overloadedSingleParam(1);

...
void overloadedSingleParam(double a) {
    // do something here..
}
void overloadedSingleParam(int a) {
    // do something here..
}

void overloadedSingleParam(int a) 是一个精确匹配,因为我们将 int 作为方法的形式参数和有效参数。
overloadedSingleParam(double a) 需要从 intdouble 的隐式转换。

所以当 int 值作为参数传递时,overloadedSingleParam(double a) 不如 void overloadedSingleParam(int a) 具体。
所以编译器选择void overloadedSingleParam(int a),编译成功


在第二种情况下,情况有所不同:您陷入了没有一种方法比另一种方法更具体的情况:

Test t = new Test();
t.overloadedTwoParam(4, 5);

...
void overloadedTwoParam(double a, int b) {
    // do something here..
}

void overloadedTwoParam(int a, double b) {
    // do something here..
}

你可以用非正式的直觉来检查它:

  • overloadedTwoParam((double)3, 4) 应用于 void overloadedTwoParam(int a, double b) 无法编译。

  • overloadedTwoParam(3, (double)4) 应用于 void overloadedTwoParam(double a, int b) 也不编译。

因此出现编译错误。