集合框架
泛型
是存储任意数据类型的模板、
可以在编译阶段进行语法检查、
不需要在进行类型转换
只能支持引用数据类型,如果是基本数据类型、会发生自动封箱的操作
泛型在类上的使用
在类上定义的泛型和对象有关,在类中成员属性和成员方法 都可以直接使用类上定义的泛型作为一种数据类型
class Person<T> {
T data ;
public void set(T data) {
this.data = data ;
}
}
在静态方法上使用泛型
静态方法中的泛型 和 类上定义的泛型没有关系,所以在静态方法中如果需要用到泛型,那么必须在返回值的前面添加一个 标记
在方法上, 参数类型 和 返回值类型 均可以用 泛型表示
如果一个静态方法 返回一个 泛型 T, 那么通常会在方法的参数中 添加一个 Class clz 作为限定返回类型的参数
class Utils{
public static <T> int compare(T a, T b) {
... ;
}
public static <T> T max(T a, T b) {
... ;
}
pulic static <T> T getBean(Class<T> clz) {
... ;
}
}
泛型的继承
// this.getClass() 获取当前类的 类对象
Class<? extends Dog> aClass = this.getClass();
// 获取 当前类的 父类 getSuperclass 获取一个类的父类
//aClass.getSuperclass();
// getGenericSuperclass() 获取一个类的带有泛型的父类
Type genericSuperclass = aClass.getGenericSuperclass();
// getClass().getName() 获取一个对象的具体类型
System.out.println(genericSuperclass.getClass().getName());
// 如果 genericSuperclass 是 ParameterizedType, 则强转并赋值给 type
if (genericSuperclass instanceof ParameterizedType type) {
//把这个类的所有泛型的类型存入数组
Type[] actualTypeArguments = type.getActualTypeArguments();
System.out.println(actualTypeArguments[0]);
}
泛型的通配符
- extends 通配符
在定义泛型的时候,可以通过 extends 关键字 来限定 泛型的类型
用来限定泛型的种类 、 上限
如果一个对象它的类型使用了 extends 通配符, 那么这个对象 只能调用 它的 读方法(生产者), 不能调用它的 修改方法(消费者)
- super 通配符
用来限定泛型的种类、 下限
如果一个对象它的类型使用了 super 通配符 , 那么这个对象 只能调用它的 消费者方法, 而不能调用它的生产者(生产者返回的永远是Object类型)
PECS 法则
PECS法则:生产者(Producer)使用extends,消费者(Consumer)使用super
1、生产者
如果你需要一个提供E类型元素的集合,使用泛型通配符<? extends E>。它好比一个生产者,可以提供数据。
2、消费者
如果你需要一个只能装入E类型元素的集合,使用泛型通配符<? super E>。它好比一个消费者,可以消费你提供的数据。
3、既是生产者也是消费者
既要存储又要读取,那就别使用泛型通配符。