泛型
泛型概述
泛型是JDK 5引入的特性,用于在编译时检查类型安全。
为什么使用泛型
java
// 没有泛型(Java 5之前)
List list = new ArrayList();
list.add("Hello");
list.add(100); // 编译通过,运行时可能出错
String s = (String) list.get(0); // 需要强制转换
String s2 = (String) list.get(1); // ClassCastException
// 使用泛型
List<String> list2 = new ArrayList<>();
list2.add("Hello");
// list2.add(100); // 编译错误,类型安全
String s3 = list2.get(0); // 无需转换泛型类
定义泛型类
java
public class Box<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
// 使用
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
System.out.println(stringBox.get());
Box<Integer> intBox = new Box<>();
intBox.set(100);
System.out.println(intBox.get());多个类型参数
java
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
// 使用
Pair<String, Integer> pair = new Pair<>("年龄", 25);
System.out.println(pair.getKey() + ": " + pair.getValue());泛型接口
定义泛型接口
java
public interface Generator<T> {
T generate();
}
// 实现类指定具体类型
public class StringGenerator implements Generator<String> {
@Override
public String generate() {
return "Hello";
}
}
// 实现类保留泛型
public class GenericGenerator<T> implements Generator<T> {
@Override
public T generate() {
return null;
}
}泛型方法
定义泛型方法
java
public class GenericMethod {
// 泛型方法
public <T> void print(T value) {
System.out.println(value);
}
// 泛型方法带返回值
public <T> T getFirst(List<T> list) {
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
// 静态泛型方法
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}
// 使用
GenericMethod gm = new GenericMethod();
gm.print("Hello");
gm.print(100);
List<String> names = Arrays.asList("张三", "李四");
String first = gm.getFirst(names);类型通配符
无界通配符 ?
java
public void printList(List<?> list) {
for (Object element : list) {
System.out.println(element);
}
// list.add("test"); // 编译错误,不能添加元素(除了null)
}
// 使用
List<String> strings = Arrays.asList("A", "B");
List<Integer> integers = Arrays.asList(1, 2);
printList(strings);
printList(integers);上界通配符 <? extends T>
java
// 只能读取,不能写入(除了null)
public double sum(List<? extends Number> list) {
double total = 0;
for (Number num : list) {
total += num.doubleValue();
}
return total;
}
// 使用
List<Integer> integers = Arrays.asList(1, 2, 3);
List<Double> doubles = Arrays.asList(1.5, 2.5);
System.out.println(sum(integers)); // 6.0
System.out.println(sum(doubles)); // 4.0下界通配符 <? super T>
java
// 只能写入T或T的子类,读取为Object
public void addNumbers(List<? super Integer> list) {
list.add(1);
list.add(2);
list.add(3);
}
// 使用
List<Number> numbers = new ArrayList<>();
addNumbers(numbers);
System.out.println(numbers); // [1, 2, 3]
List<Object> objects = new ArrayList<>();
addNumbers(objects);PECS原则
Producer Extends, Consumer Super
- 生产者(读取):使用
? extends T - 消费者(写入):使用
? super T
java
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dest.set(i, src.get(i));
}
}泛型擦除
Java泛型是编译时特性,运行时类型信息被擦除。
java
public class ErasureDemo {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();
// 运行时类型相同
System.out.println(strings.getClass() == integers.getClass()); // true
// 泛型信息被擦除
System.out.println(strings.getClass()); // class java.util.ArrayList
}
}擦除规则
- 无界类型参数
<T>擦除为Object - 有界类型参数
<T extends Number>擦除为Number - 多边界
<T extends A & B>擦除为第一个边界A
泛型限制
不能使用基本类型
java
// 错误
// List<int> list = new ArrayList<>();
// 正确:使用包装类
List<Integer> list = new ArrayList<>();不能创建泛型数组
java
// 错误
// T[] array = new T[10];
// 正确:使用Object数组或反射
@SuppressWarnings("unchecked")
T[] array = (T[]) new Object[10];不能实例化泛型
java
public class Factory<T> {
// 错误
// T instance = new T();
// 正确:传入Class对象或Supplier
public T create(Class<T> clazz) throws Exception {
return clazz.getDeclaredConstructor().newInstance();
}
}不能抛出或捕获泛型类
java
// 错误
// public class MyException<T> extends Exception { }
// 错误
// try { } catch (T e) { }泛型实战示例
泛型容器
java
public class Container<T> {
private T value;
public Container() { }
public Container(T value) {
this.value = value;
}
public T get() { return value; }
public void set(T value) { this.value = value; }
public boolean isPresent() {
return value != null;
}
public <U> Container<U> map(Function<T, U> mapper) {
return new Container<>(mapper.apply(value));
}
}泛型工具方法
java
public class GenericUtils {
// 交换数组元素
public static <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
// 查找最大值
public static <T extends Comparable<T>> T max(List<T> list) {
if (list.isEmpty()) {
return null;
}
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
// 类型转换
public static <T> List<T> castList(Class<T> clazz, List<?> list) {
List<T> result = new ArrayList<>();
for (Object item : list) {
result.add(clazz.cast(item));
}
return result;
}
}泛型Builder模式
java
public class Person {
private String name;
private Integer age;
private String city;
private Person() { }
public static <T> Builder<T> builder() {
return new Builder<>();
}
public static class Builder<T> {
private Person person = new Person();
public Builder<T> name(String name) {
person.name = name;
return this;
}
public Builder<T> age(Integer age) {
person.age = age;
return this;
}
public Builder<T> city(String city) {
person.city = city;
return this;
}
public Person build() {
return person;
}
}
}