[英]Varargs and Generics in java
請考慮以下情形:
<T> void function(T...args){
...code...
}
然后我使用Integer[]
調用它。 編譯器如何假設T
是Integer
而不是Integer[]
? (請注意,我很高興是這種情況,但是我仍然感到模棱兩可)。
此外,如果我希望T
為Integer[]
,那么我是否有必要這樣做(假設裝箱/拆箱不存在)?
Java編譯器很聰明,可以知道,因為您給了它一個Integer[]
,所以您可能打算讓T
為Integer
,而不是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.