Java 泛型(Generic)完整使用指南
一、什么是泛型?
泛型 = 类型参数化
把数据类型 当作参数传递,让类/接口/方法可以支持任意类型 ,同时在编译期检查类型安全。
作用:
- 提高代码复用性(一套代码支持多种类型)
- 类型安全,编译期就报错,不会运行时ClassCastException
- 避免强制类型转换
二、泛型的三种使用场景
1. 泛型类
java
// T 是类型参数,可以随便写:T/E/K/V 都行
public class Result<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
使用:
java
Result<String> result = new Result<>();
result.setData("hello");
String data = result.getData(); // 不用强转
2. 泛型接口
java
public interface MyService<T> {
T handle(T t);
}
实现类指定类型:
java
public class StringService implements MyService<String> {
@Override
public String handle(String s) {
return s;
}
}
3. 泛型方法
java
// 修饰符 <T> 返回值类型 方法名
public static <T> T getFirst(T[] array) {
if (array == null || array.length == 0) {
return null;
}
return array[0];
}
使用:
java
String[] arr = {"a", "b"};
String first = getFirst(arr);
三、泛型通配符(重点)
1. <?> 任意类型
java
public void show(List<?> list) { }
2. <? extends T> 上限通配符(只能取,不能存)
- T 及其子类
- 只读,不能 add(除了 null)
java
List<? extends Number> list = new ArrayList<Integer>();
3. <? super T> 下限通配符(能存能取)
- T 及其父类
- 可以 add
java
List<? super Integer> list = new ArrayList<Number>();
list.add(100);
四、泛型常用字母约定
- T:Type(类型)
- E:Element(元素,集合用)
- K:Key(键)
- V:Value(值)
- R:Result(返回值)
五、泛型的好处(对比)
不用泛型(不安全、要强转)
java
List list = new ArrayList();
list.add("abc");
String s = (String) list.get(0);
用泛型(安全、简洁)
java
List<String> list = new ArrayList<>();
list.add("abc");
String s = list.get(0);
六、泛型的重要规则(面试+坑点)
1. 泛型只在编译期有效,运行时会被擦除
java
List<String> 和 List<Integer> 在JVM里是同一个class
2. 不能使用基本类型(int/long)
必须用包装类:Integer/Long/Double
3. 静态方法不能用类泛型
java
public class A<T> {
// 错误!
public static T test(){}
}
4. ? extends 不能 add 数据(除了null)
java
List<? extends Number> list = new ArrayList<>();
list.add(1); // 编译报错
5. ? super 可以 add
java
List<? super Number> list = new ArrayList<>();
list.add(1);
list.add(1.1);
七、企业真实使用场景
- 统一返回结果
java
Result<T>
- 通用工具类
java
BeanUtils.copyProperties(source, target);
- 集合类
java
List<T>、Map<K,V>、Set<T>
- 通用接口/通用Service
八、一句话总结
泛型让类型变成参数,提高复用性与安全性;
编译期有效,运行时擦除;
extends 只读,super 可写;