簡體   English   中英

使用變量參數重載的方法

[英]Method overloading with variable argument

我認為這會是一個愚蠢的問題,但我不知道為什么會這樣。

碼;

public class OverloadingTest {
    public static int sum(int ...a){
        int sum=0;
        for(int i : a){
            sum += i;
        }
        System.out.print("this is variant args//");
        return sum;
    }

    public static double sum(double a, double b) {
        return a + b;
    }

    public static void main(String[] args) {
        System.out.println(sum(1.5, 2.5));
        System.out.println(sum(10, 20));
        System.out.println(sum(10, 20,30));
    }
}

結果我期待;

4.0
this is variant args//30
this is variant args//60

控制台中的實際結果:

 4.0 30.0 this is variant args//60 

我不能確定為什么sum(10, 20) 30.0的結果,而不是變量參數的30。

這是因為編譯器總是選擇使用最具體的方法。

由於您的第二次調用有兩個參數,並且int可以轉換為double而不會丟失精度(請參閱JLS,第5.1.2節 ),編譯器會選擇調用您的雙參數方法。

IDE會在這里警告你有關double轉換的隱式int


編輯:正如@OlegEterkhin在注釋中提到的,請參閱JLS,第15.2.2節 ,了解編譯器用於選擇將使用哪種方法的過程。

不,這不起作用:

int x = sum(10, 20);

答案在JLS第15.12.2節中 基本上,編譯器試圖找到任何適用的方法, 不必擴展varargs,只有使用varargs,如果它必須:

該過程的其余部分分為三個階段,以確保與Java SE 5.0之前的Java編程語言版本兼容。 階段是:

  • 第一階段(§15.12.2.2)執行重載解析而不允許裝箱或拆箱轉換,或使用變量arity方法調用。 如果在此階段沒有找到適用的方法,則處理繼續到第二階段。 [...]

  • 第二階段(§15.12.2.3)執行重載解析,同時允許裝箱和拆箱,但仍然排除使用變量arity方法調用。 如果在此階段沒有找到適用的方法,則處理繼續到第三階段。 [...]

  • 第三階段(§15.12.2.4)允許重載與變量arity方法,裝箱和拆箱相結合。

在這種情況下,第一階段確實找到匹配,因為sum(double, double)適用於調用sum(10, 20)因為從intdouble的隱式轉換。

在線:

System.out.println(sum(10, 20));

參數的數量sum(double a, double b)的簽名匹配sum(double a, double b) ,它是准確的方法,也是編譯器選擇的方法。

15.12.2。 編譯時步驟2:確定方法簽名以獲取詳細信息。

基於這篇文章Varargs在Java中的方法重載

選擇要選擇的重載方法,組合Boxing,Widening和Var-args時,遵循一些規則: -

Primitive widening uses the smallest method argument possible
Wrapper type cannot be widened to another Wrapper type
You can Box from int to Integer and widen to Object but no to Long
Widening beats Boxing, Boxing beats Var-args.
You can Box and then Widen (An int can become Object via Integer)
You cannot Widen and then Box (An int cannot become Long)
You cannot combine var-args, with either widening or boxing

類型推斷具有優於varargs的優先級。 由於您使用2個參數調用方法,因此在搜索varargs方法之前,它會嘗試查找與2個參數匹配(即使使用類型推斷)(即使使用正確的類型)。

此行為在規范中定義。 在第一次嘗試匹配簽名而不使用變量arity方法之后,在方法簽名解析的第三階段處理“變量方法,裝箱和取消裝箱”。

暫無
暫無

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

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