type
status
date
slug
summary
tags
category
icon
password
Property
Java的部分反射API也是泛型。例如:
Class<T>
就是泛型:调用
Class
的getSuperclass()
方法返回的Class
类型是Class<? super T>
:构造方法
Constructor<T>
也是泛型:可以声明带泛型的数组,但不能用
new
操作符创建带泛型的数组:必须通过强制转型实现带泛型的数组:
使用泛型数组要特别小心,因为数组实际上在运行期没有泛型,编译器可以强制检查变量
ps
,因为它的类型是泛型数组。但是,编译器不会检查变量arr
,因为它不是泛型数组。因为这两个变量实际上指向同一个数组,所以,操作arr
可能导致从ps
获取元素时报错,例如,以下代码演示了不安全地使用带泛型的数组:要安全地使用泛型数组,必须扔掉
arr
的引用:上面的代码中,由于拿不到原始数组的引用,就只能对泛型数组
ps
进行操作,这种操作就是安全的。带泛型的数组实际上是编译器的类型擦除:
所以不能直接创建泛型数组
T[]
,因为擦拭后代码变为Object[]
:必须借助
Class<T>
来创建泛型数组:还可以利用可变参数创建泛型数组
T[]
:谨慎使用泛型可变参数
在上面的例子中,我们看到,通过:
似乎可以安全地创建一个泛型数组。但实际上,这种方法非常危险。
以下代码来自《Effective Java》的示例:
直接调用
asArray(T...)
似乎没问题,但是在另一个方法中,返回一个泛型数组就会产生ClassCastException
,原因还是因为擦拭法,在pickTwo()
方法内部,编译器无法检测K[]
的正确类型,因此返回了Object[]
。如果仔细观察,可以发现编译器对所有可变泛型参数都会发出警告,除非确认完全没有问题,才可以用
@SafeVarargs
消除警告。如果在方法内部创建了泛型数组,最好不要将它返回给外部使用。