簡體   English   中英

方法調用中的歧義,參數類型為 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');則代碼工作正常over_Var('k', 'm');

為什么我會收到這樣的錯誤?

為什么over_Var(1, 'm'); 不模棱兩可

1是一個整數。 它不能直接傳遞給Characterchar類型的參數(沒有強制轉換),因此唯一的選擇是(float, Character...)重載。 確實存在一個intfloat擴展原始轉換,這在調用上下文中是允許的。

您可能認為1可以轉換為Character因為您可以在賦值上下文中這樣做。

Character a = 1;

然而,這純粹是因為在 JLS 的“分配上下文”部分(見上面的鏈接),有這部分開始:

此外,如果表達式是byteshortcharint類型的常量表達式(第 15.28 節):

[...]

調用上下文部分沒有這一段。 所以實際上,賦值上下文給予常量表達式(如1 )特殊處理,允許它們轉換為比實際更小的類型。 調用上下文不這樣做。

為什么over_Var('k', 'm'); 模棱兩可

在這種情況下,兩種重載都適用。 'k'是一個char ,並且在調用上下文中允許從char轉換為float (再次擴大原始轉換)。 在松散的調用上下文中也允許從charCharacter的轉換。

如果有多種適用的方法,編譯器會選擇最具體的一種。 哪個更具體? 好吧,兩個調用的第二個參數都是Character ,所以我們只需要考慮第一個參數的類型。 一個是float ,另一個是Character 其中哪一個更具體取決於它們的子類型關系。 根據子類型規則,它們是不相關的,因此兩者都不是更具體,因此您會收到編譯器錯誤。

這是規范15.12.2整個部分的簡化,我強烈建議您自行探索:)

為什么更改為char有效

不像floatCharacterfloatchar實際上是相關的! 具體來說:

  • double是一種超類型的float

  • floatlong的超類型

  • longint的超類型

  • int是一種超類型的char

  • int是一種超類型的short

  • short是一種超類型的byte

所以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 是不相關的。 (換句話說,明顯缺乏“傳遞性”的原因是特異性只能在被比較的類型的上下文中進行評估。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM