为什么转换为泛型类型会生效? [英] Why cast to generic type takes effect?
问题描述
在 Java重新访问中,代码片段如下:
class Holder< T> {
private T [] contents;
private int index = 0;
public Holder(int size){
// contents = new T [size]; //编译器错误 - 通用数组创建
contents =(T [])new Object [size]; // workaround - 将Object []转换为泛型类型
} ...}
它是根据类型擦除(我在java在线教程中检查过), T
结束为 Object
在编译的类上,所以cast (T [])
会结束为
(Object [])
,看起来没有区别,没有铸造。
那么铸件的功能或铸造的特殊含义是什么?任何提示都很感激。
需要强制转换才能告诉编译器,从我们这边来看,赋值是正确的。否则它会显示你编译器错误。
由于类型擦除,类型参数 T
在编译时被替换为擦除。
无界类型参数的删除是 Object
,而有界类型参数的删除是表示上限的类型。因此,如果类中的类型参数有一个上限 - Holder< T extends Number>
,则删除 T
将会是数字
。这意味着, T
将由编译器替换为 Number
。
因此,在这种情况下,由于 T
在无界的情况下,它的删除是 Object
。因此,编译器将它替换为 Object
。
即使该强制转换消除了编译器错误,编译器仍然会向您显示Unchecked Cast的警告。因为,如果使用 String
实例化泛型类型,则转换不是类型安全的,并且在运行时会失败 ClassCastException
>类型参数。
试试这个:
Holder< String> stringHolder = new Holder<>(5);
String [] contents = stringHolder.getContents(); // ClassCastException
一种更安全的方法来创建通用数组使用 Array.newInstance
方法。您需要将 Class< T>
参数传递给您的构造函数,然后使用以下代码:
public Holder(int size,Class< T> clazz){
contents =(T [])Array.newInstance(clazz,size);
$ / code>
在这里你也可以看到 Unchecked Cast
警告。但这是无害的。
甚至更安全的方法根本不是创建其组件类型是类型参数的数组。您可以改为使用 ArrayList< T>
。
参考:
On Java revisited ,a code excerpt goes below:
class Holder<T>{
private T[] contents;
private int index = 0;
public Holder(int size){
//contents = new T[size]; //compiler error - generic array creation
contents = (T[]) new Object[size]; //workaround - casting Object[] to generic Type
}...}
It is for generic array creation, but according to type erasure (I checked it on java online tutorial), T
ends into Object
at class compiled, so the cast (T[])
would ends into
(Object[])
, and that seems take no difference to without casting.
So what is the function of that casting or any special meaning for casting? any hint is thankful.
The cast is required to tell the compiler that the assignment is Ok from our side. Else it will show you compiler error.
Due to type erasure, the type parameter T
is replaced with it's erasure at compile time.
The erasure of an unbounded type parameter is Object
, whereas the erasure of the bounded type parameter is the type denoting the upper bound. So, if your type parameter in class had an upper bound - Holder<T extends Number>
, then the erasure of T
will be Number
. That means, T
will be replaced with Number
by the compiler.
So, in this case, since T
in unbounded, its erasure is Object
. So, it is replaced with Object
by the compiler.
Even though the casting removes the compiler error, the compiler would still show you a warning of Unchecked Cast. Because, the cast is not type safe, and would fail at runtime with ClassCastException
in case you instantiate the generic type using String
type parameter.
Try this:
Holder<String> stringHolder = new Holder<>(5);
String[] contents = stringHolder.getContents(); // ClassCastException
A safer way to create generic array is using Array.newInstance
method. You need to pass Class<T>
parameter to your constructor, and then use the following code:
public Holder(int size, Class<T> clazz){
contents = (T[]) Array.newInstance(clazz, size);
}
Here also you will see the Unchecked Cast
warning. But that is harmless.
Even safer way is not at all to create a array whose component type is a type parameter. You can rather use an ArrayList<T>
instead.
Reference:
这篇关于为什么转换为泛型类型会生效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!