通用方法
通用型別引數通常在類或介面級別定義,但方法和(很少) 建構函式也支援宣告繫結到單個方法呼叫範圍的型別引數。
class Utility // no generics at the class level
{
@SafeVarargs
public static <T> T randomOf(T first, T... rest) {
int choice = new java.util.Random().nextInt(rest.length + 1);
return choice == rest.length ? first : rest[choice];
}
public static <T extends Comparable<T>> T max(T t1, T t2) {
return t1.compareTo(t2) < 0 ? t2 : t1;
}
}
請注意,型別引數宣告 T
和 <T extends Comparable<T>>
分別出現在方法修飾符之後和返回型別之前。這允許型別引數 T
在這些方法的範圍內使用,其作用如下:
- 引數型別
- 返回型別
- 區域性變數型別
雖然上述兩種方法都使用相同的型別引數名稱 T
,但在方法級別它們完全相互獨立。編譯器將根據在呼叫該方法的每個呼叫站點處傳遞給該方法的引數來推斷實際型別。由於 max
方法宣告瞭 T extends Comparable<T>
,編譯器還強制推斷型別是 Comparable
介面的相容實現。 **
Integer num1 = 1;
Integer num2 = 2;
String str1 = "abc";
String str2 = "xyz";
Integer bigger = Utility.max(num1, num2);
assert bigger == num2;
String later = Utility.max(str2, str1);
assert later == str2;
Utility.max(num1, str1); // compiler error: num1 and str1 are incompatible types
Utility.max(new Object(), new Object()); // compiler error: Object does not implement Comparable
Java 8 顯著提高了編譯器在呼叫站點正確推斷泛型型別的能力。如果編譯器無法推斷出正確的型別,開發人員可以明確地將型別宣告為呼叫的一部分:
Object obj = Utility.<Object>randomOf(str1, new Object(), num1);