Java泛型是一种允许在类、接口和方法中使用类型参数的特性,旨在提高代码的复用性和类型安全性。通过泛型,可以在编译时进行类型检查,避免运行时出现类型转换异常,从而提升代码的安全性和可维护性。
泛型类
泛型类允许在类级别上应用泛型,其类型参数可以在整个类中使用,包括字段、方法返回类型、参数类型等。例如:
class GenericClass<T> {
private T data;
public GenericClass(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
运行
在实例化泛型类时,需要指定具体的类型参数:
GenericClass<String> stringGeneric = new GenericClass<>("Hello");
GenericClass<Integer> intGeneric = new GenericClass<>(123);
运行
泛型接口
泛型接口与泛型类类似,但用于接口。实现泛型接口的类可以选择传递具体的类型参数给接口,或者成为泛型类,将决定权交给实现它的类。例如:
interface Info<T> {
T getInfo();
}
class InfoImpl implements Info<String> {
@Override
public String getInfo() {
return "Info Implementation";
}
}
运行
泛型方法
泛型方法是在方法级别上应用泛型,其类型参数的作用域限于方法本身。例如:
public class GenericMethod {
public static <T> void printList(List<T> list) {
for (T element : list) {
System.out.println(element);
}
}
}
运行
调用泛型方法时,可以指定具体的类型参数:
List<String> stringList = Arrays.asList("A", "B", "C");
GenericMethod.printList(stringList);
运行
泛型通配符
Java中的类型通配符用?
表示,是泛型的一种特殊用法。它允许在定义泛型类、接口或方法时,使用一种更灵活的方式来指定类型参数。类型通配符可以分为三类:
- 无界通配符
?
:表示支持任意的泛型类型。 - 上界通配符
? extends T
:表示支持T
类以及T
类的子类,限制泛型的范围在T
以下。 - 下界通配符
? super T
:表示支持T
类以及T
类的父类(不限于直接父类),限制泛型的范围在T
以上。
例如:
List<?> anyList = new ArrayList<String>();
List<? extends Number> numberList = new ArrayList<Integer>();
List<? super Integer> integerList = new ArrayList<Number>();
运行
泛型的好处
- 类型安全:泛型提供类型安全检测机制,无需代码中显示类型转换,提升安全性。
- 代码重用性:通过泛型,可以编写一次代码,适应任意类型,提高代码的复用性。
- 可读性:泛型显式指定对象类型,提升代码的可读性。
泛型的使用原则
- 生产者有上限:如果需要从集合中读取元素,使用上界通配符
? extends T
。 - 消费者有下限:如果需要向集合中添加元素,使用下界通配符
? super T
。
泛型与类型擦除
Java泛型在编译时进行类型擦除,即在运行时泛型信息会被擦除,所有泛型类型参数都会被替换为其上限(通常是Object
)。因此,静态方法不能引用泛型类型,因为它们在运行时才确定类型。
总结
Java泛型是一种强大的工具,通过在类、接口和方法中使用类型参数,可以提高代码的复用性和类型安全性。泛型提供了灵活的类型检查机制,避免了运行时的类型转换异常,使得代码更加健壮和易于维护。通过合理使用泛型通配符和类型参数边界,可以进一步增强代码的灵活性和可扩展性。