如何使用泛型Java
泛型的基本概念
泛型是Java 5引入的特性,允许在类、接口或方法中使用类型参数。泛型的主要目的是提供编译时类型安全检查,并减少类型转换的需求。泛型通过类型参数化实现代码的复用性和类型安全。
泛型类
泛型类在类名后使用尖括号<>定义类型参数。类型参数可以是任何标识符,通常使用大写字母如T、E、K、V等。
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(); // 无需类型转换
泛型方法
泛型方法在方法返回类型前使用尖括号<>定义类型参数。泛型方法可以是静态或非静态的。
public class Util {
public static <T> T getMiddle(T[] array) {
return array[array.length / 2];
}
}
调用泛型方法时,编译器通常可以推断类型参数:
String[] names = {"Alice", "Bob", "Charlie"};
String middle = Util.getMiddle(names); // 类型推断为String
泛型接口
泛型接口与泛型类类似,在接口名后使用尖括号<>定义类型参数。
public interface List<T> {
void add(T element);
T get(int index);
}
实现泛型接口时,可以指定具体类型或保留类型参数:
public class ArrayList<T> implements List<T> {
// 实现方法
}
类型通配符
类型通配符?用于表示未知类型,通常用于方法参数或返回值。通配符可以结合上限或下限使用。
<? extends T>:表示类型是T或其子类。<? super T>:表示类型是T或其父类。
public void printList(List<?> list) {
for (Object elem : list) {
System.out.println(elem);
}
}
泛型限制
泛型在Java中有一些限制需要注意:
- 不能使用基本类型作为类型参数(如
int、double),必须使用包装类(如Integer、Double)。 - 不能创建泛型数组(如
new T[10])。 - 不能直接实例化类型参数(如
new T())。 - 不能在静态上下文中使用类的类型参数。
泛型与继承
泛型类或接口的继承关系与普通类不同。例如,List<String>不是List<Object>的子类。如果需要处理不同类型的泛型集合,可以使用通配符。
List<String> strings = new ArrayList<>();
List<?> objects = strings; // 合法
类型擦除
Java的泛型是通过类型擦除实现的。编译器在编译时检查类型安全,但在运行时会将类型参数擦除为其上限(通常是Object)。因此,泛型信息在运行时不可用。
Box<String> stringBox = new Box<>();
Box<Integer> intBox = new Box<>();
System.out.println(stringBox.getClass() == intBox.getClass()); // 输出true
实际应用示例
以下是一个使用泛型的实际示例,展示了如何实现一个通用的缓存类:
public class Cache<K, V> {
private Map<K, V> map = new HashMap<>();
public void put(K key, V value) {
map.put(key, value);
}
public V get(K key) {
return map.get(key);
}
}
使用示例:

Cache<String, Integer> scoreCache = new Cache<>();
scoreCache.put("Alice", 90);
int score = scoreCache.get("Alice"); // 返回90
通过泛型,可以确保键和值的类型安全,避免运行时类型错误。






