在 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 |