方法调用不明确,参数类型为 Character 和 float
Ambiguity in method invocation, with arguments type of Character and 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');
,代码工作正常
为什么我会收到这样的错误?
这里的问题是不是你有可变长度的参数。这是一个The method X is ambiguous for the type Y
error,解释在link:
If more than one member method is both accessible and applicable to a method invocation … The Java programming language uses the rule that the most specific method is chosen.
java compiler doesn’t consider any of them to be more specific, hence the method ambiguous call error
首先...为什么chars和float之间有联系?
这与字符在 Java 中的工作原理有关。
示例:
System.out.println(200 - 'a'); // subtracting a char from 200
System.out.println(0 - 'a'); // subtracting a char from 0
应该Return:
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
之间的歧义,它仍然 有错误
注释掉第二个函数。 它将失败,因为 float
转换为 Character
和 Character
之间存在歧义
注释掉第三个函数。它将打印 Method2
。它知道 char
优先于 float
!
这似乎……违反了传递性。 char + Character = 歧义。字符 + 浮点数 = 歧义。但是 char + float = 没有歧义? 留给你一个“怪”字。
编辑:这样做的原因(参见 Sweeper 的更好答案)是它知道 char
优先于 float
,因为它们是 相关类型 ; char 是 float 的子类型。另一方面, Character 不相关。 (换句话说,明显缺乏“传递性”的原因是特异性只能在被比较的类型的背景下进行评估。)
为什么over_Var(1, 'm');
没有歧义
1
是一个整数。它不能直接传递给 Character
或 char
类型的参数(不强制转换),因此唯一的选择是 (float, Character...)
重载。 是否 存在 int
到 float
加宽基元转换,这在 invocation context.
中是允许的
您可能认为 1
可以转换为 Character
,因为您可以在 assignment contexts.[=67 中做到这一点=]
Character a = 1;
然而,这纯粹是因为在 JLS 的“Assignment Contexts”部分(见上文link),有这部分开始:
In addition, if the expression is a constant expression (§15.28) of type byte
, short
, char
, or int
:
[...]
调用上下文部分没有此段。所以在现实中,赋值上下文给予常量表达式(如 1
)特殊处理,允许它们被转换为比实际更小的类型。调用上下文不会这样做。
为什么 over_Var('k', 'm');
有歧义
在这种情况下,两种重载都适用。 'k'
是一个 char
,并且在调用上下文中允许从 char
到 float
的转换(再次扩大原始转换)。在松散的调用上下文中也允许从 char
到 Character
的转换。
如果有多种适用方法,编译器会选择最具体的一种。哪个更具体?嗯,两个调用的第二个参数都是 Character
,所以我们只需要考虑第一个参数的类型。一个是 float
,另一个是 Character
。其中哪一个更具体取决于它们的子类型关系。根据 subtyping rules,它们是不相关的,所以两者都不是更具体,所以你会得到一个编译器错误。
这是对规范 15.12.2 整个部分的简化,强烈建议您自行探索:)
为什么更改为 char
有效
不像float
和Character
,float
和char
实际上是相关的!具体来说:
double
is a super type of float
float
is a super type of long
long
is a super type of int
int
is a super type of char
int
is a super type of short
short
is a super type of byte
因此 char
是 float
的子类型,因此 over_Var(char...)
比 over_Var(float, char...)
更具体,因此将是首选。
解决歧义的一些方法
要调用 (float, Character...)
,您只需施放:
over_Var((float) 'k', 'm');
要调用(Character...)
,你可以传入一个Character[]
。
over_Var(new Character[] {'k', 'm'});
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');
为什么我会收到这样的错误?
这里的问题是不是你有可变长度的参数。这是一个The method X is ambiguous for the type Y
error,解释在link:
If more than one member method is both accessible and applicable to a method invocation … The Java programming language uses the rule that the most specific method is chosen.
java compiler doesn’t consider any of them to be more specific, hence the method ambiguous call error
首先...为什么chars和float之间有联系?
这与字符在 Java 中的工作原理有关。
示例:
System.out.println(200 - 'a'); // subtracting a char from 200
System.out.println(0 - 'a'); // subtracting a char from 0
应该Return:
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
注释掉第二个函数。 它将失败,因为
之间存在歧义float
转换为Character
和Character
注释掉第三个函数。它将打印
Method2
。它知道char
优先于float
!
这似乎……违反了传递性。 char + Character = 歧义。字符 + 浮点数 = 歧义。但是 char + float = 没有歧义? 留给你一个“怪”字。
编辑:这样做的原因(参见 Sweeper 的更好答案)是它知道 char
优先于 float
,因为它们是 相关类型 ; char 是 float 的子类型。另一方面, Character 不相关。 (换句话说,明显缺乏“传递性”的原因是特异性只能在被比较的类型的背景下进行评估。)
为什么over_Var(1, 'm');
没有歧义
1
是一个整数。它不能直接传递给 Character
或 char
类型的参数(不强制转换),因此唯一的选择是 (float, Character...)
重载。 是否 存在 int
到 float
加宽基元转换,这在 invocation context.
您可能认为 1
可以转换为 Character
,因为您可以在 assignment contexts.[=67 中做到这一点=]
Character a = 1;
然而,这纯粹是因为在 JLS 的“Assignment Contexts”部分(见上文link),有这部分开始:
In addition, if the expression is a constant expression (§15.28) of type
byte
,short
,char
, orint
:[...]
调用上下文部分没有此段。所以在现实中,赋值上下文给予常量表达式(如 1
)特殊处理,允许它们被转换为比实际更小的类型。调用上下文不会这样做。
为什么 over_Var('k', 'm');
有歧义
在这种情况下,两种重载都适用。 'k'
是一个 char
,并且在调用上下文中允许从 char
到 float
的转换(再次扩大原始转换)。在松散的调用上下文中也允许从 char
到 Character
的转换。
如果有多种适用方法,编译器会选择最具体的一种。哪个更具体?嗯,两个调用的第二个参数都是 Character
,所以我们只需要考虑第一个参数的类型。一个是 float
,另一个是 Character
。其中哪一个更具体取决于它们的子类型关系。根据 subtyping rules,它们是不相关的,所以两者都不是更具体,所以你会得到一个编译器错误。
这是对规范 15.12.2 整个部分的简化,强烈建议您自行探索:)
为什么更改为 char
有效
不像float
和Character
,float
和char
实际上是相关的!具体来说:
double
is a super type offloat
float
is a super type oflong
long
is a super type ofint
int
is a super type ofchar
int
is a super type ofshort
short
is a super type ofbyte
因此 char
是 float
的子类型,因此 over_Var(char...)
比 over_Var(float, char...)
更具体,因此将是首选。
解决歧义的一些方法
要调用 (float, Character...)
,您只需施放:
over_Var((float) 'k', 'm');
要调用(Character...)
,你可以传入一个Character[]
。
over_Var(new Character[] {'k', 'm'});