Appearance
泛型
泛型是 Java 5 引入的特性,提供了编译时类型安全检测机制。
泛型概述
为什么使用泛型
java
// 不使用泛型(Java 5 之前)
List list = new ArrayList();
list.add("Hello");
list.add(123); // 编译通过,运行时可能出错
String str = (String) list.get(0); // 需要强制类型转换
String str2 = (String) list.get(1); // ClassCastException
// 使用泛型
List<String> list2 = new ArrayList<>();
list2.add("Hello");
// list2.add(123); // 编译错误,类型安全
String str3 = list2.get(0); // 无需类型转换泛型的优点
- 类型安全:编译时检查类型错误
- 消除类型转换:无需手动转换类型
- 代码复用:编写通用代码
泛型类
定义泛型类
java
public class Box<T> {
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
// 使用
Box<String> stringBox = new Box<>("Hello");
String str = stringBox.getValue();
Box<Integer> intBox = new Box<>(123);
Integer num = intBox.getValue();
// 菱形语法(Java 7+)
Box<Double> doubleBox = new Box<>(3.14);多个类型参数
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; }
@Override
public String toString() {
return "(" + key + ", " + value + ")";
}
}
// 使用
Pair<String, Integer> pair = new Pair<>("年龄", 25);
System.out.println(pair.getKey() + ": " + pair.getValue());泛型接口
定义泛型接口
java
public interface Generator<T> {
T generate();
}
// 实现方式1:指定具体类型
public class StringGenerator implements Generator<String> {
@Override
public String generate() {
return "Hello";
}
}
// 实现方式2:保留泛型
public class GenericGenerator<T> implements Generator<T> {
@Override
public T generate() {
return null;
}
}泛型接口示例
java
public interface Repository<T, ID> {
T findById(ID id);
void save(T entity);
void delete(ID id);
List<T> findAll();
}
public class UserRepository implements Repository<User, Long> {
@Override
public User findById(Long id) {
// 实现查找逻辑
return null;
}
@Override
public void save(User entity) {
// 实现保存逻辑
}
@Override
public void delete(Long id) {
// 实现删除逻辑
}
@Override
public List<User> findAll() {
// 实现查找所有逻辑
return null;
}
}泛型方法
定义泛型方法
java
public class Utils {
// 泛型方法
public static <T> void print(T value) {
System.out.println(value);
}
// 泛型方法返回值
public static <T> T getFirst(List<T> list) {
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
// 多个类型参数
public static <K, V> void printPair(K key, V value) {
System.out.println(key + " = " + value);
}
// 泛型方法与可变参数
@SafeVarargs
public static <T> List<T> createList(T... elements) {
List<T> list = new ArrayList<>();
Collections.addAll(list, elements);
return list;
}
}
// 使用
Utils.print("Hello");
Utils.print(123);
String first = Utils.getFirst(Arrays.asList("a", "b", "c"));
Utils.printPair("name", "张三");
List<String> list = Utils.createList("a", "b", "c");泛型方法与类型推断
java
public class Collections {
// 空集合
public static <T> List<T> emptyList() {
return new ArrayList<>();
}
// 类型推断
List<String> strings = Collections.emptyList();
// 显式指定类型
List<Integer> integers = Collections.<Integer>emptyList();
}类型通配符
无界通配符 ?
java
// 可以接受任何类型
public void printList(List<?> list) {
for (Object item : list) {
System.out.println(item);
}
}
List<String> strings = Arrays.asList("a", "b", "c");
List<Integer> integers = Arrays.asList(1, 2, 3);
printList(strings);
printList(integers);
// 注意:不能添加元素(除了 null)
List<?> list = new ArrayList<String>();
// list.add("hello"); // 编译错误
list.add(null); // 可以上界通配符 ? extends T
java
// 接受 T 或 T 的子类
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.1, 2.2, 3.3);
System.out.println(sum(integers)); // 6.0
System.out.println(sum(doubles)); // 6.6
// 注意:不能添加元素
List<? extends Number> list = new ArrayList<Integer>();
// list.add(1); // 编译错误下界通配符 ? super T
java
// 接受 T 或 T 的父类
public void addNumbers(List<? super Integer> list) {
list.add(1);
list.add(2);
list.add(3);
}
List<Number> numbers = new ArrayList<>();
List<Object> objects = new ArrayList<>();
addNumbers(numbers);
addNumbers(objects);
// 注意:读取时只能得到 Object
List<? super Integer> list = new ArrayList<Number>();
list.add(1);
Object obj = list.get(0); // 只能是 ObjectPECS 原则
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));
}
}
List<Integer> src = Arrays.asList(1, 2, 3);
List<Number> dest = new ArrayList<>(Arrays.asList(0, 0, 0));
copy(dest, src);类型擦除
擦除机制
java
// 泛型类
public class Box<T> {
private T value;
}
// 编译后(类型擦除)
public class Box {
private Object value;
}
// 有界类型参数
public class NumberBox<T extends Number> {
private T value;
}
// 编译后
public class NumberBox {
private Number value;
}桥接方法
java
public class StringBox extends Box<String> {
@Override
public void setValue(String value) {
super.setValue(value);
}
}
// 编译后生成桥接方法
public class StringBox extends Box {
@Override
public void setValue(String value) {
super.setValue(value);
}
// 桥接方法
public void setValue(Object value) {
setValue((String) value);
}
}泛型限制
不能使用基本类型
java
// 错误
// List<int> list = new ArrayList<>();
// 正确:使用包装类
List<Integer> list = new ArrayList<>();不能实例化类型参数
java
public class Factory<T> {
// 错误
// T instance = new T();
// 正确:使用反射
public T create(Class<T> clazz) throws Exception {
return clazz.getDeclaredConstructor().newInstance();
}
}不能创建泛型数组
java
// 错误
// T[] array = new T[10];
// 正确:使用 Object 数组或反射
@SuppressWarnings("unchecked")
T[] array = (T[]) new Object[10];
// 或使用 Array.newInstance
T[] array = (T[]) Array.newInstance(clazz, 10);不能使用泛型类型的静态成员
java
public class Box<T> {
// 错误
// private static T value;
// 错误
// public static T getValue() { return value; }
// 正确:静态方法可以使用自己的类型参数
public static <E> E process(E value) {
return value;
}
}不能抛出或捕获泛型类实例
java
// 错误
// public class MyException<T> extends Exception { }
// 错误
// try { } catch (T e) { }
// 正确:在方法签名中声明
public <T extends Throwable> void throwException(Class<T> clazz) throws T {
// ...
}泛型实战
泛型容器
java
public class Container<T> {
private Map<String, T> map = new HashMap<>();
public void put(String key, T value) {
map.put(key, value);
}
public T get(String key) {
return map.get(key);
}
public T getOrDefault(String key, T defaultValue) {
return map.getOrDefault(key, defaultValue);
}
public boolean contains(String key) {
return map.containsKey(key);
}
public void remove(String key) {
map.remove(key);
}
public Set<String> keys() {
return map.keySet();
}
public Collection<T> values() {
return map.values();
}
}
// 使用
Container<String> container = new Container<>();
container.put("name", "张三");
container.put("city", "北京");
System.out.println(container.get("name"));泛型工具类
java
public class GenericUtils {
// 判断是否为空
public static <T> boolean isEmpty(T[] array) {
return array == null || array.length == 0;
}
// 判断是否为空(集合)
public static <T> boolean isEmpty(Collection<T> collection) {
return collection == null || collection.isEmpty();
}
// 获取第一个元素
public static <T> Optional<T> first(List<T> list) {
if (isEmpty(list)) {
return Optional.empty();
}
return Optional.of(list.get(0));
}
// 获取最后一个元素
public static <T> Optional<T> last(List<T> list) {
if (isEmpty(list)) {
return Optional.empty();
}
return Optional.of(list.get(list.size() - 1));
}
// 数组转列表
@SafeVarargs
public static <T> List<T> toList(T... elements) {
List<T> list = new ArrayList<>();
Collections.addAll(list, elements);
return list;
}
// 列表转数组
public static <T> T[] toArray(List<T> list, Class<T> clazz) {
@SuppressWarnings("unchecked")
T[] array = (T[]) Array.newInstance(clazz, list.size());
return list.toArray(array);
}
// 过滤
public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
List<T> result = new ArrayList<>();
for (T item : list) {
if (predicate.test(item)) {
result.add(item);
}
}
return result;
}
// 映射
public static <T, R> List<R> map(List<T> list, Function<T, R> mapper) {
List<R> result = new ArrayList<>();
for (T item : list) {
result.add(mapper.apply(item));
}
return result;
}
}泛型构建器
java
public class Builder<T> {
private T value;
private final List<Consumer<T>> operations = new ArrayList<>();
public Builder<T> with(Consumer<T> operation) {
operations.add(operation);
return this;
}
public Builder<T> with(T initialValue) {
this.value = initialValue;
return this;
}
public T build() {
operations.forEach(op -> op.accept(value));
return value;
}
public static <T> Builder<T> of(T initialValue) {
return new Builder<T>().with(initialValue);
}
}
// 使用
class Person {
String name;
int age;
void setName(String name) { this.name = name; }
void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
Person person = Builder.of(new Person())
.with(p -> p.setName("张三"))
.with(p -> p.setAge(25))
.build();
System.out.println(person);类型安全的异构容器
java
public class TypeSafeContainer {
private final Map<Class<?>, Object> map = new HashMap<>();
public <T> void put(Class<T> type, T instance) {
map.put(type, instance);
}
public <T> T get(Class<T> type) {
return type.cast(map.get(type));
}
public <T> boolean contains(Class<T> type) {
return map.containsKey(type);
}
}
// 使用
TypeSafeContainer container = new TypeSafeContainer();
container.put(String.class, "Hello");
container.put(Integer.class, 123);
container.put(Double.class, 3.14);
String str = container.get(String.class);
Integer num = container.get(Integer.class);
Double d = container.get(Double.class);