微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

方法调用中的歧义,参数类型为 Character 和 float 为什么 over_Var(1, 'm'); 没有歧义为什么 over_Var('k', 'm'); 不明确为什么改为 char 有效解决歧义的一些方法

如何解决方法调用中的歧义,参数类型为 Character 和 float 为什么 over_Var(1, 'm'); 没有歧义为什么 over_Var('k', 'm'); 不明确为什么改为 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');
    }
}

我收到这样的错误

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 的扩展原始转换,这在 invocation context 中是允许的。

您可能认为可以将 1 转换为 Character,因为您可以在 assignment contexts 中这样做。

Character a = 1;

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

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

[...]

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

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

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

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

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

为什么改为 char 有效

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

  • doublefloat

    的超类型
  • floatlong

    的超类型
  • longint

    的超类型
  • intchar

    的超类型
  • intshort

    的超类型
  • shortbyte

    的超类型

所以 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 error,在链接中解释:

如果多个成员方法既可访问又适用于方法调用……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

    之间的歧义,它仍然会出现错误
  • 注释掉第二个函数。 由于 float 被转换为 CharacterCharacter

    之间的歧义,它会失败
  • 注释掉第三个函数。它将打印 Method2。它知道将 char 置于 float 之上!

这似乎……违反了传递性。字符 + 字符 = 歧义。字符 + 浮点数 = 歧义。但是 char + float = 无歧义? 我会给你留下“奇怪”这个词

编辑:这样做的原因(请参阅 Sweeper 的更好答案)是它知道将 char 置于 float 之上,因为它们是相关类型; char 是 float 的子类型。另一方面, Character 是不相关的。 (换句话说,明显缺乏“传递性”的原因是特异性只能在被比较的类型的上下文中进行评估。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。