簡體   English   中英

Java中的Varargs和泛型

[英]Varargs and Generics in java

請考慮以下情形:

<T> void function(T...args){
   ...code...
}

然后我使用Integer[]調用它。 編譯器如何假設TInteger而不是Integer[] (請注意,我很高興是這種情況,但是我仍然感到模棱兩可)。

此外,如果我希望TInteger[] ,那么我是否有必要這樣做(假設裝箱/拆箱不存在)?

Java編譯器很聰明,可以知道,因為您給了它一個Integer[] ,所以您可能打算讓TInteger ,而不是Integer[] 我假設這是Java語言規范的一部分,該規范將...定義為varargs。

如果要指定T是什么,則可以使用以下語法進行操作:

Integer[] ary = { 1, 2, 3 };
myObj.function(ary); // T is Integer
myObj.<Integer>function(ary); // T is Integer
myObj.<Integer[]>function(ary); // T is Integer[]


<Integer>function(ary); // this is invalid; instead you could do...
this.<Integer>function(ary); // this if it's an instance method
MyClass.<Integer>function(ary); // or this if it's static

泛型適用於對象引用,因此<T>將適用於類的對象引用。 int[]是引用int數組的類,而int是基元。 Integer[]是一個引用Integer數組的類,其中Integer是另一個類。

對此進行回顧之后,varargs參數T ... args需要一個對象引用數組,因此int[]將是對象引用數組中的單個元素,而Integer[]是對象引用數組。

如果要發送Integer[]作為varargs的每個元素,則可以發送Integer[][] 我寫了一個例子:

public class SomeMain {

    static <T> void foo(T...ts) {
        for(T t : ts) {
            System.out.println(t);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] ints = { 1, 2, 3 };
        Integer[] integers = { 1, 2, 3 };
        foo(ints);
        foo(integers);
        //note, here each element in the varags will behave as Integer[]
        foo(new Integer[][] { integers });
    }
}

輸出(數組的哈希碼將在每次運行時更改):

[I@8dc8569

1
2
3

[Ljava.lang.Integer;@45bab50a

尋找適用的方法分為三個階段。 在第一階段,javac嘗試完全匹配參數類型和方法參數類型。 參數類型的方法的是T[]在此階段,參數類型為Integer[]后兩個matche T被推斷為Integer ,因此該方法被選擇作為適用方法(沒有其他重載方法來考慮)。 沒有進一步的階段。

如果第一階段沒有產生適用的方法,則javac將繼續其他階段。 例如,如果T被顯式指定為Integer[] ,則該方法在第一階段將不匹配(因為T[]Integer[]不匹配)

在第三階段,考慮使用varargs。 javac會將T而不是T[]與尾隨參數類型進行匹配。

確實,這非常令人困惑,並且似乎與我們的直覺相矛盾。

請注意,泛型與問題並不完全相關。 如果函數簽名為void function(Object... args) ,則將出現完全相同的問題—如果您傳遞Integer[]類型的表達式,則可以解釋為將數組用作args或作為元素之一的args

答案是,基本上,如果可能的話,編譯器將更喜歡將參數用作args 由於您傳遞的表達式具有“引用類型的數組”類型,因此它與args兼容,因此該解釋為准。

此外,如果我想讓T為Integer [],那么我是否有必要這樣做(假設裝箱/拆箱不存在)?

由於它是通用方法,因此可以在調用時顯式指定type參數: this.<Integer[]>function(...)

回到更普遍的問題,函數簽名是void function(Object... args) 您可以自己顯式創建參數數組:

function(new Integer[][]{ myIntegerArray });

或者(更簡單),您可以將表達式轉換為不再是引用類型數組的類型:

function((Object)myIntegerArray);

暫無
暫無

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

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