泛型¶
写过 TypeScript 泛型?Java 泛型你会觉得毫无压力。<T> 就是类型参数,用的时候才确定具体类型。
泛型集合¶
List<String> names = new ArrayList<>(); // <> 钻石操作符:右边类型可省
names.add("Tom");
// names.add(123); // ✗ 编译报错
String s = names.get(0); // 拿出来就是 String,不用强转
没有泛型的年代,集合放 Object,取出来要强转、容易 ClassCastException。泛型把这个错误提前到编译期。
自定义泛型类¶
class Box<T> {
private T value;
public T get() { return value; }
public void set(T value) { this.value = value; }
}
Box<Integer> intBox = new Box<>(99);
Box<String> strBox = new Box<>("hi");
对标 TS 的 class Box<T> {}。
泛型方法¶
对标 TS 的 function firstOf<T>(list: T[]): T。
常用约定字母¶
| 字母 | 含义 | 常见场景 |
|---|---|---|
T |
Type 类型 | 通用 |
E |
Element 元素 | 集合 List<E> |
K/V |
Key / Value | Map Map<K,V> |
R |
Return 返回 | 函数式接口 |
Spring 里你会见到的¶
List<Task>—— 任务列表ResponseEntity<T>—— HTTP 响应包装- MyBatis-Plus 的
BaseMapper<T>、IService<T>—— 泛型限定实体类型
泛型是第三篇读懂 Spring 代码的钥匙之一。
完整可运行示例¶
package com.javaglm.language.ch14;
import java.util.ArrayList;
import java.util.List;
/**
* 第 14 章 · 泛型。
* 对标 TS 的泛型:<T> 是类型参数,用的时候才确定具体类型。
* 好处:类型安全 + 免去强转。Spring / MyBatis-Plus 大量使用泛型。
*/
public class GenericDemo {
public static void main(String[] args) {
// 1. 泛型集合:限定元素类型,对标 TS 的 string[]
List<String> names = new ArrayList<>(); // 右边的 <> 叫"钻石操作符",可省略类型
names.add("Tom");
// names.add(123); // ✗ 编译报错,只能放 String
String first = names.get(0); // 拿出来直接是 String,不用强转
System.out.println("first = " + first);
// 2. 自定义泛型类:对标 TS 的 class Box<T>
Box<Integer> intBox = new Box<>(99);
Box<String> strBox = new Box<>("hello");
System.out.println("intBox = " + intBox.get() + ", strBox = " + strBox.get());
// 3. 泛型方法:<T> 声明类型参数,对标 TS 的 function firstOf<T>(arr: T[]): T
System.out.println("firstOf = " + firstOf(names));
}
/** 泛型方法:T 是类型参数,在调用时由实参推断。 */
static <T> T firstOf(List<T> list) {
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
}
/** 泛型类:Box<T>,T 在实例化时才确定类型。 */
class Box<T> {
private T value;
Box(T value) {
this.value = value;
}
public T get() {
return value;
}
public void set(T value) {
this.value = value;
}
}
:octicons-arrow-left-16: 上一章:集合框架 | 下一章:Lambda 与函数式接口