泛型(Generics)是 Java 5 引入的重要特性之一,它允许在定义类、接口和方法时使用类型参数化。通过泛型,我们可以在编写代码时不指定具体类型,而是在使用时再传入具体的类型。
Map map = new HashMap();
map.put("key", "value");
String s = (String) map.get("key"); // 必须强制类型转换
如果有人插入了 Integer
类型的值,运行时会抛出 ClassCastException
。
Map map = new HashMap<>();
String s = map.get("key"); // 不需要强制类型转换
泛型帮助我们在编译期就发现类型错误,提高了程序的安全性和可读性。
优势 | 描述 |
---|---|
类型安全 | 编译器会在编译阶段检查类型是否匹配,避免运行时异常 |
消除强制类型转换 | 提高代码可读性和安全性 |
代码复用 | 同一套逻辑适配多种数据类型 |
更好的性能表现 | 减少不必要的类型检查与转换 |
public class Box {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
使用方式:
Box stringBox = new Box<>();
stringBox.setItem("Hello");
String content = stringBox.getItem(); // 不需要强转
public interface Container {
void add(T item);
T get(int index);
}
实现该接口的类也需要使用泛型:
public class ListContainer implements Container {
private List list = new ArrayList<>();
public void add(T item) {
list.add(item);
}
public T get(int index) {
return list.get(index);
}
}
public class Util {
public static T getFirst(List list) {
return list.isEmpty() ? null : list.get(0);
}
}
调用方式:
List names = Arrays.asList("Alice", "Bob");
String first = Util.getFirst(names); // 自动推断为 String 类型
符号 | 含义 |
---|---|
T |
Type,通用类型 |
E |
Element,集合元素 |
K |
Key,键 |
V |
Value,值 |
N |
Number,数字类型 |
List intList = new ArrayList<>();
List numberList = intList; // ❌ 编译错误!
这是为了防止将 Float
添加进 List
中,破坏类型安全。
?
当不需要关心具体类型时,可以使用通配符:
public void printList(List> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
还可以结合上下限使用:
extends T>
:表示 T 或其子类 super T>
:表示 T 或其父类只能使用包装类型,如 Integer
、Double
等,不能直接使用 int
、double
。
Java 的泛型是通过类型擦除实现的,即在运行时泛型信息会被擦除:
List list1 = new ArrayList<>();
List list2 = new ArrayList<>();
System.out.println(list1.getClass() == list2.getClass()); // true
这意味着泛型只存在于编译阶段。
下面是一个简单的泛型容器类 Lhist
:
public class Lhist {
private V[] array;
private int size;
public Lhist(int capacity) {
array = (V[]) new Object[capacity];
}
public void add(V value) {
if (size == array.length)
throw new IndexOutOfBoundsException();
array[size++] = value;
}
public V get(int index) {
if (index >= size)
throw new IndexOutOfBoundsException();
return array[index];
}
public int size() {
return size;
}
}
使用方式:
Lhist stringList = new Lhist<>(10);
stringList.add("Hello");
System.out.println(stringList.get(0)); // 输出 Hello
Java 标准库从 Java 5 开始全面支持泛型,尤其是集合框架:
Collection
List
Set
Map
Queue
例如:
List names = new ArrayList<>();
names.add("Tom");
String name = names.get(0); // 无需强转
还广泛使用了通配符和边界限定:
public boolean addAll(Collection extends E> c);
特点 | 描述 |
---|---|
类型安全 | 在编译期检查类型,避免运行时异常 |
消除强制类型转换 | 提高代码可读性和安全性 |
代码复用 | 一份逻辑适配多种类型 |
通配符 | 支持灵活的类型匹配(? , ? extends T , ? super T ) |
类型擦除 | 运行时无泛型信息,仅保留原始类型 |
如果你觉得这篇文章对你有帮助,欢迎点赞 + 收藏 + 关注我,后续将持续更新 Java 技术干货内容!