详解 Java 泛型:核心概念与实用示例
Java 泛型(Generics)是Java SE 5引入的一项特性,旨在提高代码的可重用性和类型安全性。通过泛型,开发者可以编写一个通用的类、接口或方法,可以与多种类型一起工作,而不需要为每种类型创建不同的版本。
泛型的核心概念
泛型类(Generic Class):
泛型类是包含一个或多个类型参数的类。例如:
public class Box<T> { private T content; public void setContent(T content) { this.content = content; } public T getContent() { return content; } }
这里,T 是类型参数,可以在创建 Box 对象时指定具体的类型:
Box<String> stringBox = new Box<>(); stringBox.setContent("Hello"); Box<Integer> integerBox = new Box<>(); integerBox.setContent(123);
泛型方法(Generic Method):
泛型方法是包含类型参数的方法。类型参数在方法的声明中被指定。例如:
public class GenericMethodExample { public static <T> void printArray(T[] array) { for (T element : array) { System.out.println(element); } } public static void main(String[] args) { Integer[] intArray = {1, 2, 3, 4}; String[] stringArray = {"A", "B", "C"}; printArray(intArray); printArray(stringArray); } }
泛型接口(Generic Interface):
泛型接口和泛型类类似。它们允许类型参数在接口中使用。例如:
public interface Pair<K, V> { K getKey(); V getValue(); } public class OrderedPair<K, V> implements Pair<K, V> { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } }
类型通配符(Wildcard):
泛型中的通配符用于表示未知类型。通配符有三种形式:
- 无限制通配符(?):表示任何类型。
public void printList(List<?> list) { for (Object elem : list) { System.out.println(elem); } }
- 有上限的通配符(? extends Type):表示类型是 Type 或其子类。
public void processList(List<? extends Number> list) { for (Number num : list) { System.out.println(num); } }
- 有下限的通配符(? super Type):表示类型是 Type 或其父类。
public void addNumber(List<? super Integer> list) { list.add(new Integer(123)); }
类型擦除(Type Erasure):
泛型在编译时会进行类型擦除,这意味着泛型类型在运行时被移除,并替换为其限定类型(如果未指定,则为 Object)。这使得泛型可以与非泛型代码互操作。
public class Box<T> { private T content; public void setContent(T content) { this.content = content; } public T getContent() { return content; } }
编译后:
public class Box { private Object content; public void setContent(Object content) { this.content = content; } public Object getContent() { return content; } }
使用泛型的注意事项
不能创建泛型类型的实例:
public class Box<T> { // T t = new T(); // 错误:不能直接创建泛型类型的实例 }
静态成员不能使用类型参数:
public class Box<T> { // private static T content; // 错误:静态变量不能使用类型参数 }
泛型数组创建受限:
public class Box<T> { // T[] array = new T[10]; // 错误:不能直接创建泛型数组 }
示例:使用泛型的栈
public class GenericStack<T> { private List<T> stack = new ArrayList<>(); public void push(T element) { stack.add(element); } public T pop() { if (!stack.isEmpty()) { return stack.remove(stack.size() - 1); } return null; } public boolean isEmpty() { return stack.isEmpty(); } public static void main(String[] args) { GenericStack<String> stringStack = new GenericStack<>(); stringStack.push("Hello"); stringStack.push("World"); System.out.println(stringStack.pop()); // 输出:World GenericStack<Integer> intStack = new GenericStack<>(); intStack.push(1); intStack.push(2); System.out.println(intStack.pop()); // 输出:2 } }
结论
Java 泛型提供了一种类型安全的方式来实现通用编程。它们不仅提高了代码的可读性和可维护性,还避免了类型转换的错误。在编写通用类、接口和方法时,泛型是一个强大的工具。