一、泛型的概念
(一)概念
泛型是jdk5引入的概念,可以在在定义类、接口和方法时使用类型参数。这些类型参数在代码编写时代表一种抽象的类型,在使用这些类、接口或方法时再指定为具体的类型。例如,在 Java 中可以定义一个泛型类Box,其中T就是类型参数,在使用时可以创建Box或Box等不同类型的Box实例。
(二)作用
泛型主要用于创建可复用的代码结构,使代码能够处理多种不同类型的数据,同时保持类型安全。它在数据结构(如列表、映射等)和算法(如排序、搜索等)的实现中被广泛应用。
二、泛型的好处
(一)代码复用性
1. 减少代码重复
可以编写通用的类、接口和方法,避免为每种可能的数据类型编写重复的代码。例如,一个泛型的列表类可以存储任何类型的对象,而不需要针对整数、字符串等不同类型分别编写列表类。
2. 提高开发效率
由于减少了代码重复,开发人员可以更快地编写代码,并且在需要修改代码逻辑时,只需要在一个通用的代码结构中进行修改,而不是在多个针对不同类型的类似代码中分别修改。
(二)类型安全性
1. 编译时类型检查
泛型在编译时进行类型检查,确保类型的正确性。例如,如果定义了一个Box,编译器会阻止将一个String类型的值放入这个Box中,从而避免了在运行时可能出现的类型错误,如ClassCastException。
2. 增强代码可读性
通过明确指定泛型类型,代码的可读性得到提高。例如,看到List就很容易理解这个列表是用来存储字符串的,而不是其他类型的数据。
三、泛型的细节
(一)类型擦除
1. 概念
在 Java 等编程语言中,泛型存在类型擦除的特性。这意味着在编译后,泛型类型信息会被擦除。例如,List和List在运行时的类型实际上是相同的(都是java.util.List类型)。
2. 影响
由于类型擦除,一些操作在泛型环境下可能会受到限制。例如,不能直接创建一个泛型类型的数组(如T[],其中T是泛型类型参数),因为在运行时无法确定T的具体类型。
(二)泛型嵌套
示例
泛型可以嵌套使用。例如,Map<String, List>是一个合法的泛型嵌套结构,表示一个键为字符串类型,值为整数列表类型的映射。这种嵌套结构可以表示更复杂的数据关系。
四、泛型的定义
(一)泛型类
在类的声明中定义类型参数。例如:
class GenericClass<T> {
private T data;
public GenericClass(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
在这个例子中,GenericClass是一个泛型类,T是类型参数,可以在创建类实例时指定T为具体的类型,如GenericClass0。
(二)泛型接口
在接口的声明中定义类型参数。例如:
interface GenericInterface<T> {
T getValue();
}
当一个类实现这个泛型接口时,需要指定接口中的类型参数为具体的类型。例如:
class ImplementingClass implements GenericInterface<Integer> {
@Override
public Integer getValue() {
return 5;
}
}
(三)泛型方法
在方法的签名中定义类型参数。例如:
class UtilityClass {
public static <T> T[] copyOf(T[] original, int newLength) {
// 方法实现逻辑
return newArray;
}
}
在这个例子中,定义了一个泛型方法,T的具体类型由调用该方法时传入的数组的原始类型决定。
五、泛型的继承
泛型不具备继承性:
方法里面的形参是一个集合,集合的泛型是Animal。调用method方法时,只能传递Animal,不可传递调Animal的子类Dog、Cat…
public static void method(ArrayList<Animal> list){
}
数据具备继承性:
集合的泛型是Animal,往集合添加数据时,可以添加Animal对象,还可以添加Animal的所有子类对象
ArrayList<Animal> list = new ArrayList<>();
list.add(new Animal());
list.add(new Dog());
list.add(new HuskyDog());
六、泛型的通配符
(一)无界通配符(<?>)
1. 含义
无界通配符可以匹配任何类型。例如,List<?>表示一个未知类型的列表。它在某些情况下很有用,比如当编写一个方法,只需要对列表中的元素进行遍历操作而不关心元素的具体类型时,可以使用无界通配符。
2. 局限性
由于无界通配符表示未知类型,所以不能向使用无界通配符的集合中添加元素(除了null),因为编译器无法确定要添加元素的类型是否正确。
(二)上界通配符(<? extends T>)
上界通配符表示 匹配 指定类型T或者T的子类型。
例如,List<? extends Animal>表示这个列表中的元素是Animal类型或者Animal的子类型(如Dog、Cat等)。
(三)下界通配符(<? super T>)
下界通配符表示匹配指定类型T或者T的父类型。例如,List<? super Cat>表示这个列表中的元素是Cat类型或者Cat的父类型(如Animal等)。