核心概念
Java 泛型是 Java SE 1.5 引入的一项重要特性,它的核心思想是 参数化类型(Parameterized Types),即通过将数据类型作为参数传递给类、接口或方法,使代码能够灵活地处理多种类型,同时保证类型安全性。
一、类型参数【<T>】
1. 泛型类/接口
在类名后添加类型参数 <T>,T 是占位符(可以是任意标识符),声明后类的占位符会被替换成对应类型
public class Box<T> {
private T content;
public void setContent(T content) { this.content = content; }
public T getContent() { return content; }
}
// 使用
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello");
String value = stringBox.getContent(); // 无需强制转换
2.泛型接口
public interface ITest<T> {
void show(T t);
}
public class TestImpl implements ITest<String> {
@Override
public void show(String t) {
System.out.println(t);
}
}
3.泛型方法
修饰符 <T> 返回值类型 方法名(T 变量名){//......}
- 作为传参:在方法返回类型前声明类型参数 <T>:
public <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
// 调用时可显式指定类型或由编译器推断
printArray(new Integer[]{1, 2, 3});
- 作为返回值:使用 Class<T> 参数传递类型信息
public <T> T convert(Object input, Class<T> targetType) {
if (targetType == String.class) {
return targetType.cast(input.toString()); // 转成 String
} else if (targetType == Integer.class) {
return targetType.cast(Integer.parseInt(input.toString())); // 转成 Integer
}
throw new IllegalArgumentException("不支持的类型: " + targetType);
}
//调用
String strResult = convert(123, String.class); // 返回 "123"(String 类型)
Integer intResult = convert("456", Integer.class); // 返回 456(Integer 类型)
- 作为返回值:依赖泛型类型推断保证类型安全
public static <T> T getFirst(List<T> list) {
if (list.isEmpty()) return null;
return list.get(0);
}
//调用
List<String> list = Arrays.asList("1","2","3","4","5");
String result = getFirst(list);
二、通配符【?】

1. 无界通配符 <?>
- 作为传参:表示接受任何类型
public void processList(List<?> list) {
for (Object elem : list) { /* ... */ }
}
- 作为返回值:表示返回任何类型。
通配符 ? 不能直接作为方法的返回类型,Java 编译器无法确定实际类型,而List<?>是List的子类型
public List<?> getData() {
List<Food> resultList = new ArrayList<>();
return resultList;
}
2. 上界通配符 <? extends T>
接受 T 或其子类(适合读取数据):
public double sum(List<? extends Number> list) {
double sum = 0.0;
for (Number num : list) { sum += num.doubleValue(); }
return sum;
}
3. 下界通配符 <? super T>
接受 T 或其父类(适合写入数据):
public void addNumbers(List<? super Integer> list) {
list.add(1);
list.add(2);
}
4. PECS 原则(Producer-Extends, Consumer-Super)
- 生产者(Producer):提供数据时用 extends(如 List<? extends T>)
- 消费者(Consumer):消费数据时用 super(如 List<? super T>)
三、实际应用场景
1. REST API 响应封装
public class ApiResponse<T> {
private int code;
private String message;
private T data; // 泛型数据
// 构造方法和Getter/Setter
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(200);
response.setData(data);
return response;
}
}
// 使用
ApiResponse<User> userResponse = ApiResponse.success(user);
ApiResponse<List<Product>> productResponse = ApiResponse.success(products);
2.Java 的集合框架(如 ArrayList<T>, HashMap<K,V>)
List<String> names = new ArrayList<>();
names.add("Alice");
String name = names.get(0); // 不需要强制转换
3.工具类方法
泛型方法可用于编写通用的工具类,例如排序、查找等。
public static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
四、总结
<T> 通常比 ? 更优,除非你明确需要以下通配符的特性:
1.接受未知泛型参数(如 List<?> 可接受任何 List<T>)
2.遵循 PECS 原则(Producer-Extends, Consumer-Super)
3.编写更灵活的 API(如 Java 标准库中的 Collections.copy())
4.但在大多数业务代码中,<T> 是更好的选择,原因如下:
782

被折叠的 条评论
为什么被折叠?



