方法重载:单参数与交替参数
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
)
当谈到交替使用 int
和 double
参数的其他方法时,编译器不想负责决定是否将第一个参数提升为 double
或 double
的第二个参数。
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)
需要从 int
到 double
的隐式转换。
所以当 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)
也不编译。
因此出现编译错误。
这个问题可能类似于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
)
当谈到交替使用 int
和 double
参数的其他方法时,编译器不想负责决定是否将第一个参数提升为 double
或 double
的第二个参数。
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)
需要从 int
到 double
的隐式转换。
所以当 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)
也不编译。
因此出现编译错误。