Java-泛型
Java-泛型
多重型態參數
在 Java 中,泛型(Generics)讓我們可以將「型態」延後到使用時才指定,讓程式更具彈性與可重用性。
舉例來說,你可以建立一個通用的 Example<K, V> 類別,用來表示一個 key 對應一個 value
class Example<K, V>{
}
//人對應一個名子(字串)
Example<String, Person> ex1 = new Example<String, Person>();
//區域對應一個數字
Example<Integer, Region> ex2 = new Example<Integer, Region>();
泛型參數的使用範圍
有兩個地方你無法在類別裡面使用泛型參數
- 不能用在靜態變數上
- 泛型類別的型別參數(例如 T)不能直接用在靜態方法中,不論是方法的參數還是回傳值,因為靜態方法不屬於任何具體型別的物件
錯誤範例
class Gen<T>{
static T value;
public static void test1(T v1){
}
public static T test2(){
}
}
泛型的靜態變數
即使你使用不同的型別來建立泛型類別實例,這些實例共用同一個靜態變數。因為靜態變數是類別層級的,而不是泛型實例化後各自擁有的。
方法自帶的泛型
class Box<T> {
public static <U> U echo(U value) {
return value;
}
}
這裡的 <U> 是屬於這個方法本身的泛型參數,與類別的 T 無關,因此合法、可編譯
小結
| 錯誤場景 | 編譯結果 |
|---|---|
static T someVar; |
編譯錯誤 |
public static T method() |
編譯錯誤 |
public static void method(T t) |
編譯錯誤 |
public static <U> U method(U u) |
合法 |
Java 的泛型(Generics)只能使用參考型別(Reference Type),不能用原始型別(Primitive Type)
-
原始型別(primitive types):像
int、double、char、boolean,這些是效率較高的基本資料型別,不是物件。 -
參考型別(reference types):像
Integer、Double、Character、Boolean,這些是物件(classes),包裝了原始型別。
List<int> numbers = new ArrayList<>(); // 錯誤!不能用原始型別 int
List<Integer> numbers = new ArrayList<>(); // 用 Integer(參考型別)包裝 int
這是因為 Java 的泛型設計時,是用「類別」來實作的,所以泛型只能接受 物件型別(即參考型別)
一般方法參數可以用 int 嗎
泛型的限制只出現在「泛型參數」中,但一般方法中的參數可以是任何型別
public void printInt(int value) {
System.out.println(value);
}
Java 有一種自動轉換稱為「裝箱與拆箱(Boxing / Unboxing)
List<Integer> list = new ArrayList<>();
list.add(10); // 自動 boxing: int → Integer
int x = list.get(0); // 自動 unboxing: Integer → int
泛型支援原始型別,可以考慮 Java 8 之後的 IntStream、OptionalInt 或一些特殊的泛型工具(如 Guava 的 PrimitiveSpecialized),或使用泛型+手動處理 boxing/unboxing