在 Java 泛型和函數式編程中,T
、R
和 O
都是類型參數(Type Parameters),它們的主要區別在于命名約定和上下文含義,而不是語言層面的區別。它們可以互換使用,但通常遵循一定的命名習慣以提高代碼可讀性。
1. 常見泛型參數命名約定
類型參數 | 典型含義 | 常見使用場景 |
---|---|---|
T | Type(通用類型) | 表示任意類型,通常用于輸入參數或通用類 |
R | Result(結果類型) | 表示函數或方法的返回類型 |
O | Output(輸出類型) | 類似于 R ,表示輸出類型 |
E | Element(集合元素類型) | 常用于集合類(如 List<E> ) |
K | Key(鍵類型) | 用于 Map<K, V> 的鍵 |
V | Value(值類型) | 用于 Map<K, V> 的值 |
U | 第二個泛型類型 | 當需要多個泛型參數時使用 |
? | 無界通配符 | 用于表示未知類型, 在泛型中提供了更靈活的用法,特別是在處理集合類時非常有用 |
2. T
vs R
vs O
vs ?
的區別
(1) T
(Type)
- 表示輸入參數的類型,通常用于:
- 泛型類(如
List<T>
) - 函數式接口的輸入參數(如
Predicate<T>
)
- 泛型類(如
- 示例:
public class Box<T> {private T value; // T 可以是任何類型 }
(2) R
(Result)
- 表示返回結果的類型,通常用于:
- 函數式接口的返回值(如
Function<T, R>
) - 方法返回值的泛型
- 函數式接口的返回值(如
- 示例:
Function<String, Integer> strToLength = s -> s.length(); // T=String, R=Integer
(3) O
(Output)
- 類似于
R
,表示輸出類型,但不如R
常見 - 通常用于自定義函數式接口(如
MapFunction<T, O>
) - 示例:
@FunctionalInterface interface MapFunction<T, O> {O map(T input); // T=輸入類型,O=輸出類型 }
(4) ?
? 是 Java 泛型中的通配符(wildcard),用于表示未知類型。它在泛型中提供了更靈活的用法,特別是在處理集合類時非常有用。
4.1基本用法
4.1.1. 無界通配符 <?>
表示可以接受任何類型:
List<?> list = new ArrayList<String>(); // 可以接受任何泛型類型的List
4.1.2. 上界通配符 <? extends T>
表示類型必須是 T
或其子類:
List<? extends Number> numbers = new ArrayList<Integer>(); // 可以是Number的任何子類
4.1.3. 下界通配符 <? super T>
表示類型必須是 T
或其父類:
List<? super Integer> list = new ArrayList<Number>(); // 可以是Integer的任何父類
4.2.使用場景
4.2.1. 讀取數據(extends 生產者)
// 使用上界通配符,只能讀取
void printNumbers(List<? extends Number> numbers) {for (Number n : numbers) {System.out.println(n);}// numbers.add(1); // 編譯錯誤,因為不確定具體類型
}
4.2.2. 寫入數據(super 消費者)
// 使用下界通配符,可以寫入
void addIntegers(List<? super Integer> list) {list.add(1);list.add(2);// Integer i = list.get(0); // 編譯錯誤,只能獲取Object類型
}
4.2.3. 既讀又寫
// 不使用通配符,可以讀寫
void processList(List<Integer> list) {list.add(1);Integer i = list.get(0);
}
4.3. 重要規則
-
PECS原則(Producer-Extends, Consumer-Super):
- 生產者(只讀)使用
extends
- 消費者(只寫)使用
super
- 生產者(只讀)使用
-
通配符不能用于泛型類的實例化:
List<?> list = new ArrayList<?>(); // 編譯錯誤
-
通配符不能用于泛型方法的類型參數:
<T> void method(List<T> list) {} // 正確 <?> void method(List<?> list) {} // 編譯錯誤
示例代碼
public class WildcardExample {public static void main(String[] args) {// 上界通配符示例List<Integer> intList = Arrays.asList(1, 2, 3);printNumbers(intList);// 下界通配符示例List<Number> numList = new ArrayList<>();addIntegers(numList);System.out.println(numList); // 輸出 [1, 2]}// 上界通配符 - 只讀static void printNumbers(List<? extends Number> numbers) {numbers.forEach(System.out::println);}// 下界通配符 - 可寫static void addIntegers(List<? super Integer> list) {list.add(1);list.add(2);}
}
接口/類 | 輸入類型 | 輸出類型 | 說明 |
---|---|---|---|
Function<T, R> | T | R | Java 標準庫 |
MapFunction<T, O> | T | O | 自定義接口 |
Predicate<T> | T | boolean | 返回固定類型 |
Supplier<T> | 無 | T | 無輸入,返回 T |