Java泛型相关总结(下)

时间:2023-01-28 04:12:15

约束与局限性

不能用基本类型实例化类型参数

不能像Pair<double>这样调用,只能Pair<Double>,原因是类型擦除

运行时类型查询只使用于原始类型

虚拟机中的对象属于一个特定的非泛型类型,类型查询只能产生原始类型。

Pair<String> stringPair = ...;
Pair<Employee> employeePair = ...;
if (stringPair.getClass() == employeePair.getClass()) //相等的

不能创建参数化类型的数组

因为类型擦除会导致数组元素类型不安全

不能创建数组,但可以声明类型为Pair<String>[]的变量

向可变参数方法传递泛型类型实例,虚拟机会创建泛型类型数组,且会提示一个警告,使用@SupressWarnings("unchecked")或@SafeVarargs标注。

不能实例化类型变量
不能使用 new T(...)、new T[...]、T.class这样的类型变量

不能构造泛型数组
这里有数组中的一个知识点,数组类型之间不能强制类型转换,当Object[]引用赋给Comparable[]变量时,将会发生ClassCastException异常
擦除导致的
在静态方法中,构造静态方法有两种方式:
1.让用户提供数组构造器方法

public static <T extends Comparable> T[] minmax(IntFunction<T[]> constr, T... a) {
T[] mm = constr.apply(2);
...
}

2.使用反射

private static <T extends Comparable> T[] minmax2(T... args) {
T[] mm = (T[])Array.newInstance(args.getClass().getComponentType(), 2);
...
}

不能在静态域、静态方法中引用类型变量

会有编译时错误

不能抛出或捕获泛型类的对象,泛型类扩展Throwable是不合法的

可以消除对受查异常的检查

擦除后的冲突,比如以下泛型方法在擦除后会与Object的equals()产生冲突
public boolean equals(T value) {
return first.equals(value);
}
补救的办法是重新命名引发错误的方法。

泛型的继承规则

无论S与T有什么关系,Pair<S>与Pair<T>没有什么关系,以下代码有编译错误

Manager[] topHonchos = ...;
Pair<Employee> result = ArrayAlg.minmax(topHonchos); //error

在数组中,可以将一个Manager[]对象赋予一个Employee[]的变量,但虚拟机会监控数组元素的类型,如果试图将一个Employee对象存储到该数组中,会抛出ArrayStoreException异常

可以将参数化类型转化为原始类型,Pair<Employee>是原始类型Pair的子类。

泛型类可以扩展或实现其他泛型类,如ArrayList<Employee>类实现List<Employee>接口。

通配符类型

通配符类型,允许类型参数变化,定义如下。

Pair<? extends Employee>

此时的继承关系是,Pair<Employee> 或 Pair<Manager> > Pair<? extends Employee > Pair(原始类型)

超类型限定(supertype bound)

Pair<? super Manager>

超类型限定限制为Manager的所有超类型。

带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。