[英]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');
則代碼工作正常over_Var('k', 'm');
為什么我會收到這樣的錯誤?
over_Var(1, 'm');
不模棱兩可 1
是一個整數。 它不能直接傳遞給Character
或char
類型的參數(沒有強制轉換),因此唯一的選擇是(float, Character...)
重載。 確實存在一個int
到float
擴展原始轉換,這在調用上下文中是允許的。
您可能認為1
可以轉換為Character
因為您可以在賦值上下文中這樣做。
Character a = 1;
然而,這純粹是因為在 JLS 的“分配上下文”部分(見上面的鏈接),有這部分開始:
此外,如果表達式是
byte
、short
、char
或int
類型的常量表達式(第 15.28 節):[...]
調用上下文部分沒有這一段。 所以實際上,賦值上下文給予常量表達式(如1
)特殊處理,允許它們轉換為比實際更小的類型。 調用上下文不這樣做。
over_Var('k', 'm');
模棱兩可在這種情況下,兩種重載都適用。 'k'
是一個char
,並且在調用上下文中允許從char
轉換為float
(再次擴大原始轉換)。 在松散的調用上下文中也允許從char
到Character
的轉換。
如果有多種適用的方法,編譯器會選擇最具體的一種。 哪個更具體? 好吧,兩個調用的第二個參數都是Character
,所以我們只需要考慮第一個參數的類型。 一個是float
,另一個是Character
。 其中哪一個更具體取決於它們的子類型關系。 根據子類型規則,它們是不相關的,因此兩者都不是更具體,因此您會收到編譯器錯誤。
這是規范15.12.2整個部分的簡化,我強烈建議您自行探索:)
char
有效不像float
和Character
, float
和char
實際上是相關的! 具體來說:
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');
要調用(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');
}
}
由於char
和Character
之間的歧義,這將產生錯誤。
注釋掉第一個函數。 由於char
和Character
之間的歧義,它仍然會出現錯誤
注釋掉第二個函數。 由於float
轉換為Character
和Character
之間的歧義,它將失敗
注釋掉第三個函數。 它將打印Method2
。 它知道將char
優先於float
!
這似乎……違反了傳遞性。 字符 + 字符 = 歧義。 字符 + 浮點數 = 歧義。 但是 char + float = 無歧義? 我會給你留下“奇怪”這個詞。
編輯:這樣做的原因(請參閱 Sweeper 的更好答案),是它知道將char
優先於float
因為它們是相關類型; char 是 float 的子類型。 另一方面, Character 是不相關的。 (換句話說,明顯缺乏“傳遞性”的原因是特異性只能在被比較的類型的上下文中進行評估。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.