为什么转换为泛型类型会生效? [英] Why cast to generic type takes effect?

查看:110
本文介绍了为什么转换为泛型类型会生效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆