目录
一、是什么
在Java中,集合存在一个缺点,即当对象添加到集合中后,集合会失去对该对象的具体数据类型的记忆,导致在取出对象时,集合将其视为Object类型。这是因为集合的设计者在创建时无法确定集合将被用来存储哪种类型的对象,因此选择设计成能够存储任何类型的对象,以保持通用性。
这种设计带来了两个问题:
1、集合对元素类型没有限制,可能导致一些问题。比如,你想创建一个只能保存Dog对象的集合,但程序却可以轻松将Cat对象添加进去,可能引发异常【存进去】
2、由于集合存储时丢失了对象的具体类型信息,取出对象后通常需要进行强制类型转换。这不仅增加了编程的复杂性,还可能引发ClassCastException异常【取出来】
为了解决这些问题,Java5引入了泛型的概念,允许在创建集合时指定集合元素的具体类型。使用泛型后,程序员不能轻易地将不同类型的对象添加到集合中,而且在取出元素时无需进行强制类型转换,使得代码更加安全和简洁。
二、使用
2.1 泛型类
在类的声明中使用尖括号引入类型参数,然后在类中使用这个类型参数
public class Box<T> {
private T value;
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
在实例化时,制定具体的类型:
Box<Integer> integerBox = new Box<>();
integerBox.setValue(42);
Box<String> stringBox = new Box<>();
stringBox.setValue("Hello");
2.2 泛型方法
在方法声明中使用尖括号引入类型参数,然后在方法中国使用这个类型参数。调用泛型方法时,编译器通常可以从上下文推断出类型参数,无需显式指定。
public <T> T genericMethod(T[] array) {
// 实现泛型⽅法的逻辑
}
2.3 泛型接口
类似于泛型类,泛型接口在声明时引入参数类型,然后在接口的方法中使用这个参数类型。
public interface List<T> {
void add(T element);
T get(int index);
}
三、泛型擦除
是指在编译时期,Java编译器会将泛型信息从泛型代码中移除,以便保持与Java早期版本的兼容性
影响:
1、类型参数的擦除:在编译时,泛型类、接口和方法中的类型参数会被擦除为它们的上界。例如,List<T>在编译时会被擦除为List<Object>
2、桥方法的生成:在泛型类或接口中,如果有泛型方法并且涉及到泛型类型参数的类型转换,编译器会生成桥方法来保证类型安全。这是为了解决擦除后可能导致类型不匹配问题
3、泛型数组的限制:由于泛型擦除,不能直接创建泛型数组。集合中的泛型是不可变的,但是数组里的类型是可变的。数组先天就允许将子类数组应用赋值给父类数组,所以导致无法在编译期检查数组的类型安全问题,这个与泛型的初衷相违背,导致数组无法使用泛型