Java泛型详解
什么是泛型
泛型(Generics)是JDK 5引入的特性,它允许在定义类、接口和方法时使用类型参数。泛型提供了编译时类型安全检测,避免了运行时的ClassCastException。
泛型类
泛型类是在类定义时指定类型参数的类。
public class Box<T> {
private T content;
public Box(T content) {
this.content = content;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
}
public class GenericClassDemo {
public static void main(String[] args) {
Box<String> stringBox = new Box<>("Hello Generics");
System.out.println("String Box: " + stringBox.getContent());
Box<Integer> intBox = new Box<>(12345);
System.out.println("Integer Box: " + intBox.getContent());
}
}
多类型参数
泛型类可以有多个类型参数,用逗号分隔。
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 "Pair{key=" + key + ", value=" + value + "}";
}
}
public class MultiGenericDemo {
public static void main(String[] args) {
Pair<String, Integer> nameAge = new Pair<>("张三", 25);
Pair<Integer, Boolean> scorePass = new Pair<>(95, true);
System.out.println(nameAge);
System.out.println(scorePass);
}
}
泛型接口
泛型接口是在接口定义时使用类型参数的接口。
public interface Repository<T, ID> {
T findById(ID id);
void save(T entity);
void delete(ID id);
}
public class UserRepository implements Repository<User, Long> {
@Override
public User findById(Long id) {
return new User(id, "张三");
}
@Override
public void save(User entity) {
System.out.println("保存用户: " + entity.getName());
}
@Override
public void delete(Long id) {
System.out.println("删除用户ID: " + id);
}
}
泛型方法
泛型方法是在方法签名中声明自己的类型参数的方法。
public class GenericMethodDemo {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
public static <T extends Comparable<T>> T findMax(T[] array) {
T max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i].compareTo(max) > 0) {
max = array[i];
}
}
return max;
}
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3, 4, 5};
String[] strArray = {"Java", "Python", "C++"};
printArray(intArray);
printArray(strArray);
System.out.println("最大整数: " + findMax(intArray));
System.out.println("最大字符串: " + findMax(strArray));
}
}
类型通配符
通配符用于解决泛型的协变和逆变问题。
import java.util.ArrayList;
import java.util.List;
public class WildcardDemo {
public static void printList(List<?> list) {
for (Object item : list) {
System.out.print(item + " ");
}
System.out.println();
}
public static double sumOfList(List<? extends Number> list) {
double sum = 0;
for (Number num : list) {
sum += num.doubleValue();
}
return sum;
}
public static void addNumbers(List<? super Integer> list) {
list.add(1);
list.add(2);
list.add(3);
}
public static void main(String[] args) {
List<String> strings = List.of("Java", "Python", "C++");
printList(strings);
List<Integer> integers = List.of(1, 2, 3, 4, 5);
List<Double> doubles = List.of(1.5, 2.5, 3.5);
System.out.println("整数和: " + sumOfList(integers));
System.out.println("浮点数和: " + sumOfList(doubles));
List<Number> numberList = new ArrayList<>();
addNumbers(numberList);
System.out.println("添加后: " + numberList);
}
}
泛型约束
使用extends关键字可以约束泛型必须继承自某个类或实现某个接口。
import java.util.ArrayList;
import java.util.List;
public class BoundedTypeDemo {
public static <T extends Comparable<T>> void sortAndPrint(List<T> list) {
list.sort(T::compareTo);
System.out.println("排序结果: " + list);
}
public static <T extends Number & Comparable<T>> T findMax(List<T> list) {
T max = list.get(0);
for (int i = 1; i < list.size(); i++) {
if (list.get(i).compareTo(max) > 0) {
max = list.get(i);
}
}
return max;
}
public static void main(String[] args) {
List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
sortAndPrint(names);
List<Integer> numbers = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9, 2, 6));
sortAndPrint(numbers);
}
}
类型擦除
Java泛型是通过类型擦除实现的,编译后泛型类型信息会被擦除。
public class TypeErasureDemo {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(stringList.getClass() == intList.getClass());
System.out.println("运行时类型: " + stringList.getClass().getName());
}
}
泛型最佳实践
- 使用泛型保证类型安全
- 避免使用原始类型(Raw Type)
- 合理使用通配符处理继承关系
- 了解类型擦除的限制
- 在API设计中优先使用泛型
总结
泛型是Java类型系统的核心特性,它使代码更加安全、灵活和可重用。理解泛型类、泛型方法、通配符和类型擦除的概念,对于编写高质量的Java代码至关重要。