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

MRM*_*MRM 5 java character char

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');
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到这样的错误:

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
Run Code Online (Sandbox Code Playgroud)

如果我使用char而不是 ,代码工作正常Character,或者删除该行over_Var('k', 'm');

为什么我会收到这样的错误?

Swe*_*per 7

为什么over_Var(1, 'm');不暧昧

1是一个整数。它不能传递给类型Characterchar直接(没有强制转换)的参数,因此唯一的选择是(float, Character...)重载。有确实存在一个intfloat加宽原语转换,其在被允许调用上下文

你可能有想到的是1可以转换为一个Character,因为你可以做,在作业环境

Character a = 1;
Run Code Online (Sandbox Code Playgroud)

然而,这纯粹是因为在 JLS 的“分配上下文”部分(见上面的链接),有这部分开始:

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

[...]

调用上下文部分没有这一段。所以实际上,赋值上下文给予常量表达式(如1)特殊处理,允许它们转换为比实际更小的类型。调用上下文不这样做。

为什么over_Var('k', 'm');有歧义

在这种情况下,两种重载都适用。'k'是 a char,并且在调用上下文中允许从chartofloat转换(再次扩大原始转换)。在松散的调用上下文中也允许从charto转换Character

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

这是规范15.12.2整个部分的简化,我强烈建议您自行探索 :)

为什么要char改行

floatand不同Characterfloatchar实际上是相关的!具体来说:

  • double 是一种超级类型 float

  • float 是一种超级类型 long

  • long 是一种超级类型 int

  • int 是一种超级类型 char

  • int 是一种超级类型 short

  • short 是一种超级类型 byte

所以char是 的子类型float,所以over_Var(char...)比 更具体over_Var(float, char...),因此将是首选。

解决歧义的一些方法

要调用(float, Character...),您只需投射:

over_Var((float) 'k', 'm');
Run Code Online (Sandbox Code Playgroud)

要调用(Character...),您可以传入一个Character[].

over_Var(new Character[] {'k', 'm'});
Run Code Online (Sandbox Code Playgroud)