泛型就是类型参数化,让类、接口、方法能够处理多种数据类型,而不需要为每种类型都写一份代码。
当你发现要为一个新类型复制粘贴代码时,就该考虑用泛型了!
泛型就像是Java的"万能模板",一份代码,多种用途,既安全又高效。
泛型类、接口、方法
// 语法:class 类名<类型参数>
使用场景
总结:什么时候用泛型?
强烈建议使用泛型的场景:
- 集合操作:List、Set、Map必须用,保证类型安全
- 工具类:处理多种类型数据的工具
- API响应:统一格式的接口返回
- 通用组件:会被多处复用的代码
- 数据转换:不同类型间的转换
List<T>- 列表
Map<K, V>- 键值对
响应结果<T>- 返回数据
基本语法格式
- 泛型类的写法
java
// 语法:class 类名<类型参数> { ... }
// 这里的T就像"占位符",用的时候再确定具体类型
class 盒子<T> { // 1. 在类名后面加<T>
// 2. 在类里面,T可以当作一种类型来用
private T 里面的东西; // 这里T是"某种东西的类型"
public 盒子(T 东西) { // 构造方法参数也是T
this.里面的东西 = 东西;
}
public T 拿出来() { // 返回类型也是T
return 里面的东西;
}
}
- 多个类型参数
java
// 语法:class 类名<T, U, V> { ... }
// 可以定义多个类型参数,用逗号隔开
class 双人座<T, U> { // T和U是两个不同的类型
private T 左边的人;
private U 右边的人;
public 双人座(T 左, U 右) {
this.左边的人 = 左;
this.右边的人 = 右;
}
public T 左边是谁() {
return 左边的人;
}
public U 右边是谁() {
return 右边的人;
}
}
创建对象的写法
- 完整的写法
java
// 完整的写法:类名<具体类型> 变量名 = new 类名<具体类型>();
盒子<String> 苹果盒子 = new 盒子<String>("苹果");
// 前面的<String>告诉编译器:这是一个装String的盒子
// 后面的<String>重复了,有点啰嗦
- 简化的写法(推荐)
java
// Java 7+ 可以这样写:类名<具体类型> 变量名 = new 类名<>();
盒子<String> 苹果盒子 = new 盒子<>("苹果");
// 后面用空的<>,编译器会自动推断是String
// 这叫"钻石语法",像钻石<>的形状
- 空的<>是什么意思?
java
// 1. 创建对象时的空<>
盒子<String> 盒子1 = new 盒子<>("苹果");
// 这个<>表示"和前面一样的类型"
// 编译器看到前面是<String>,就知道后面也是String
// 2. 如果不写<>会怎样?
盒子<String> 盒子2 = new 盒子("苹果"); // 有警告,不推荐
// 这叫"原始类型",相当于没有泛型检查
规则
规则1:声明时用<T>
规则2:使用时指定具体类型
规则3:空的<>表示"和前面一样"
规则4:类型安全检查
统一返回结果的用例
java
public class Result<T> {
private Integer code;//业务状态码 0-成功 1-失败
private String message;//提示信息
private T data;//响应数据
//快速返回操作成功响应结果(带响应数据)
public static <T> Result<T> success(T data) {
//这里的T省略了,因为可以根据上下文推断出这里应该是什么类型。如果不能推断出,这里就要写上
return new Result<>(0, "操作成功", data);
}
//快速返回操作成功响应结果
public static <T> Result<T> success() {
return new Result<>(0, "操作成功", null);
}
public static <T> Result<T> error(String message) {
return new Result<>(1, message, null);
}
}