21. 什么是泛型?为什么要使用泛型?
大约 3 分钟
**泛型(Generics)**是Java语言的一种特性,它允许在定义类、接口和方法时使用类型参数,从而使代码可以处理不同类型的对象,而不需要编写重复的代码。泛型提供了一种类型安全的方式来编写可重用的代码。
泛型的定义
泛型类:在类定义中使用类型参数。
public class Box<T> { private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } }
泛型方法:在方法定义中使用类型参数。
public <T> void printArray(T[] array) { for (T element : array) { System.out.println(element); } }
泛型接口:在接口定义中使用类型参数。
public interface Container<T> { void add(T item); T get(int index); }
为什么要使用泛型?
使用泛型有以下几个主要的好处:
1. 类型安全
泛型可以在编译时检查类型错误,从而避免运行时出现ClassCastException
。这使得代码更安全,因为类型转换是在编译时完成的,而不是在运行时。
List<String> list = new ArrayList<>();
list.add("Hello");
// list.add(10); // 编译错误,避免了将非String类型对象添加到list中
2. 代码复用
泛型允许编写能够处理多种类型的类、方法或接口,从而提高代码的复用性。使用泛型可以避免编写重复的代码。
public class Box<T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
Box<Integer> intBox = new Box<>();
intBox.setItem(123);
Box<String> strBox = new Box<>();
strBox.setItem("Hello");
3. 消除强制类型转换
在没有泛型之前,使用集合类时,必须手动进行类型转换。泛型可以消除这些强制类型转换,使代码更简洁和可读。
List list = new ArrayList();
list.add("Hello");
String str = (String) list.get(0); // 需要强制类型转换
// 使用泛型后
List<String> list = new ArrayList<>();
list.add("Hello");
String str = list.get(0); // 不需要强制类型转换
4. 提高代码的可读性和可维护性
泛型让开发者在编写和阅读代码时明确数据类型,从而减少了潜在的错误,并使代码更加直观和容易理解。
泛型的使用示例
泛型类
public class Pair<T, U> {
private T first;
private U second;
public Pair(T first, U second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public U getSecond() {
return second;
}
}
泛型方法
public class GenericMethod {
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};
String[] strArray = {"A", "B", "C"};
printArray(intArray);
printArray(strArray);
}
}
限定泛型
上限通配符(extends):表示类型参数必须是某个类的子类或实现某个接口。
public <T extends Number> void printNumber(T number) { System.out.println(number); }
下限通配符(super):表示类型参数必须是某个类的超类,用于消费类型。
java复制代码public void addNumbers(List<? super Integer> list) { list.add(10); }
总结
泛型在Java中通过引入类型参数,使得类、接口和方法能够处理不同类型的数据,并在编译时提供类型安全的检查。使用泛型的主要原因是为了提高代码的类型安全性、复用性、可读性和可维护性。泛型在集合框架、算法库等众多场景中广泛使用,极大地提高了代码的灵活性和健壮性。