方法调用中的歧义,参数类型为Character和float


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是一个整数。它不能直接传递给Characterchar类型的参数(不带强制转换),因此唯一的选项是(float, Character...)重载。是否存在intfloat扩展原语转换,这在调用上下文中是允许的。

您可能认为1可以转换为Character,因为您可以在分配上下文中这样做。

Character a = 1;

然而,这纯粹是因为在";Assignment Contexts";JLS的部分(见上面的链接),有一部分开始:

此外,如果表达式是byteshortcharint类型的常量表达式(§15.28):

[…]

调用上下文的部分没有此段落。因此,在现实中,赋值上下文对常量表达式(如1)进行了特殊处理,允许它们转换为比实际更小的类型。调用上下文不能做到这一点。

为什么over_Var('k', 'm');不明确

在这种情况下,两种重载都适用。'k'char,并且在调用上下文中允许从charfloat的转换(再次加宽基元转换)。从charCharacter的转换在松散调用上下文中也是允许的。

如果有多个适用的方法,编译器会选择最具体的方法。哪个更具体?好吧,两个调用的第二个参数都是Character,所以我们只需要考虑第一个参数的类型。一个是CCD_ 26,另一个是CCD_。其中哪一个更具体取决于它们的分型关系。根据子类型规则,它们是不相关的,所以两者都不是更具体的,所以你会得到一个编译器错误。

这是对规范15.12.2的整个部分的简化,我强烈鼓励您自己探索:)

为什么更改为char有效

floatCharacter不同,floatchar实际上是相关的!具体而言:

  • doublefloat的超类型

  • CCD_ 35是CCD_

  • CCD_ 37是CCD_

  • CCD_ 39是CCD_

  • CCD_ 41是CCD_

  • CCD_ 43是CCD_

因此charfloat的亚型,因此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');
}
}
  • 由于charCharacter之间的模糊性,此将出现错误

  • 注释掉第一个函数。由于charCharacter之间的模糊性,它仍将具有错误

  • 注释掉第二个函数由于作为Character广播的floatCharacter之间的模糊性,它将失败

  • 注释掉第三个函数。它将打印Method2。它知道char优先于float

显示。。。违反及物性。char+Character=歧义。Character+float=歧义。但是char+float=不含糊我给你留下一个词";奇怪的">

编辑:原因是(请参阅Sweeper的更好答案),因为它知道char优先于float,因为它们是相关类型;char是float的一个子类型。另一方面,Character是不相关的。(换句话说,明显缺乏"传递性"的原因是,特异性只能在被比较的类型的背景下进行评估。)

相关内容

  • 没有找到相关文章

最新更新