public class Main {
static void over_Var(float a, Character... ab) {
System.out.println("Method1");
}
static void over_Var(Character... ab) {
System.out.println("Method2");
}
public static void main(String[] args) {
System.out.println("Hello World");
over_Var(1, 'm');
over_Var('k', 'm');
}
}
我得到的错误如下:
Main.java:19: error: reference to over_Var is ambiguous
over_Var('k', 'm');
^
both method over_Var(float, Character...) in Main and method over_Var(Character...) in Main
match 1 error
如果我使用char
而不是Character
,或者删除行over_Var('k', 'm');
,代码工作正常
为什么我会犯这样的错误?
为什么over_Var(1, 'm');
不含糊
1
是一个整数。它不能直接传递给Character
或char
类型的参数(不带强制转换),因此唯一的选项是(float, Character...)
重载。是否存在int
到float
扩展原语转换,这在调用上下文中是允许的。
您可能认为1
可以转换为Character
,因为您可以在分配上下文中这样做。
Character a = 1;
然而,这纯粹是因为在";Assignment Contexts";JLS的部分(见上面的链接),有一部分开始:
此外,如果表达式是byte
、short
、char
或int
类型的常量表达式(§15.28):
[…]
调用上下文的部分没有此段落。因此,在现实中,赋值上下文对常量表达式(如1
)进行了特殊处理,允许它们转换为比实际更小的类型。调用上下文不能做到这一点。
为什么over_Var('k', 'm');
不明确
在这种情况下,两种重载都适用。'k'
是char
,并且在调用上下文中允许从char
到float
的转换(再次加宽基元转换)。从char
到Character
的转换在松散调用上下文中也是允许的。
如果有多个适用的方法,编译器会选择最具体的方法。哪个更具体?好吧,两个调用的第二个参数都是Character
,所以我们只需要考虑第一个参数的类型。一个是CCD_ 26,另一个是CCD_。其中哪一个更具体取决于它们的分型关系。根据子类型规则,它们是不相关的,所以两者都不是更具体的,所以你会得到一个编译器错误。
这是对规范15.12.2的整个部分的简化,我强烈鼓励您自己探索:)
为什么更改为char
有效
与float
和Character
不同,float
和char
实际上是相关的!具体而言:
double
是float
的超类型CCD_ 35是CCD_
CCD_ 37是CCD_
CCD_ 39是CCD_
CCD_ 41是CCD_
CCD_ 43是CCD_
因此char
是float
的亚型,因此over_Var(char...)
比over_Var(float, char...)
更具特异性,因此将是优选的。
解决歧义的一些方法
要调用(float, Character...)
,只需投射:
over_Var((float) 'k', 'm');
要调用(Character...)
,可以传入一个Character[]
。
over_Var(new Character[] {'k', 'm'});
这里的问题是而不是您有可变长度的参数。这是一个The method X is ambiguous for the type Y
错误,在链接中解释:
如果一个方法调用可访问并适用于多个成员方法…Java编程语言使用选择最特定方法的规则。
java编译器不认为它们中的任何一个更具体,因此方法调用错误不明确
首先。。。为什么字符和浮点之间有联系
这与Java中字符在后台的工作方式有关。
示例:
System.out.println(200 - 'a'); // subtracting a char from 200
System.out.println(0 - 'a'); // subtracting a char from 0
应返回:
103
-97
那么解决方案是什么呢?您指示了一个:将Character
更改为char
。但为什么会这样呢?您偶然发现了非常有趣的Java行为。以这个代码为例:
public class Main {
static void over_Var(float a, Character b) {
System.out.println("Method1");
}
static void over_Var(char a, Character b) {
System.out.println("Method2");
}
static void over_Var(Character a, Character b) {
System.out.println("Method3");
}
public static void main(String[] args) {
over_Var('k','m');
}
}
由于
char
和Character
之间的模糊性,此将出现错误。注释掉第一个函数。由于
char
和Character
之间的模糊性,它仍将具有错误注释掉第二个函数由于作为
Character
广播的float
和Character
之间的模糊性,它将失败注释掉第三个函数。它将打印
Method2
。它知道char
优先于float
!
显示。。。违反及物性。char+Character=歧义。Character+float=歧义。但是char+float=不含糊我给你留下一个词";奇怪的">。
编辑:原因是(请参阅Sweeper的更好答案),因为它知道char
优先于float
,因为它们是相关类型;char是float的一个子类型。另一方面,Character是不相关的。(换句话说,明显缺乏"传递性"的原因是,特异性只能在被比较的类型的背景下进行评估。)