Java泛型错误[重复]

Posted

技术标签:

【中文标题】Java泛型错误[重复]【英文标题】:Java Generics Error [duplicate] 【发布时间】:2012-05-11 00:35:13 【问题描述】:

可能重复:Java how to: Generic Array creationError: Generic Array Creation

我收到此错误:

Cannot create a generic array of T

这是我的代码(第 6 行错误):

1    public class HashTable<T> 
2    
3        private T[] array;
4    
5        HashTable(int initSize) 
6            this.array = new T[initSize];
7        
8    

我想知道为什么会出现这个错误以及修复它的最佳解决方案。谢谢。

更新:

我调整了我的代码,以便数组改为采用链表,但我收到了一个新错误。

这是我的错误:

Cannot create a generic array of LinkedList<T>

这是我的代码(第六行错误):

1    public class HashTable<T> 
2    
3        private LinkedList<T>[] array;
4    
5        HashTable(int initSize) 
6            this.array = new LinkedList<T>[initSize];
7        
8    

此错误是否出于完全相同的原因?我只是假设我可以创建通用链表并将它们存储在数组中。

【问题讨论】:

这可能是不可能的:***.com/a/217110(认为这不太一样) ***.com/questions/529085/… 这是因为类型擦除,见:docs.oracle.com/javase/tutorial/java/generics/erasure.html 你不想要一个链表数组——你只需要一个链表(或 ArrayList)并将其视为一个数组!即与 AlexR 的回答完全相同。 ArrayList 是数组周围的简单 Collection 包装器。 我实际上是在实现一个哈希表(对于某个实现)需要数组来保存数组列表。我发现简单的转换方法最适合我的场景。 (LinkedList[])(new LinkedList[initSize]) 【参考方案1】:

是的,不能创建泛型数组。 我知道的最好的解决方法是使用集合:

private List<T> list;

.......

list = new ArrayList<T>();

【讨论】:

这不正确,如我的回答中所示,通用数组可以被创建。 并非没有(ewwwwww)反射。【参考方案2】:

泛型数组可以通过反射创建(尽管需要不安全的强制转换),您只需要将类作为参数传递(假设以下方法在定义@的类内部987654321@类型参数):

@SuppressWarnings("unchecked")
public T[] createArray(Class<T> klass, int size) 
    return (T[]) Array.newInstance(klass, size);

例如,在您的情况下:

HashTable<Integer> t = new HashTable<Integer>();
Integer[] intArray = t.createArray(Integer.class, 4);
intArray[0] = 1; intArray[1] = 2;
intArray[2] = 3; intArray[3] = 4;

System.out.println(Arrays.toString(intArray));
> [1, 2, 3, 4]

【讨论】:

这是一个反射创建的数组,不安全地转换为泛型类型。不确定它是否会算作通用数组创建。至少它不适合我。对我来说,关键是在运行时没有完整的泛型类型信息,因此不可能实例化一个新的 T。 虽然这个解决方案需要强制转换和警告抑制,但它显示了一个很好的解决方法。我认为这里的所有人都给出了有用的答案。 (T[])Array.newInstance() 就像 (T[])new Object[](T[])new ArrayList&lt;T&gt;().toArray()。 @Amir Pashazadeh 完美解释了所有这些解决方案“不清楚” @edalorzo 你是对的,我在答案的开头添加了一个警告 @Alex (T[]) new Object[] 会不会最终导致ClassCastException?因为数组是可具体化的,而Object 的数组不是T 的数组,因此据我所知,这个演员永远不会成功。如果是这样,这不能与建议的答案相同。由于同样的原因,两者都不会成功 toArray() 方法。【参考方案3】:

您不能创建 T(在 Java 中),但 T[] 在内部与 对象[]。

public class HashTable<T> 

    private T[] array;

    @SuppressWarnings("unchecked")
    HashTable(int initSize) 
        this.array = (T[]) new Object[initSize];
    

(会编译,我检查过)

由于 newacct 的 cmets,最好只使用 Object[] 并将项目转换为 T。

public class HashTable<T> 

    private Object[] array;

    public HashTable(int initSize) 
        this.array = new Object[initSize];
    

    public void put(String pKey, T pItem) 
       ...
       array[x] = pItem;
       ....
    
    public T get(String pKey) 
       ...
       return (T) array[x];
    

【讨论】:

是的,但是您必须小心,因为如果您有一个方法将该数组作为T[] 返回到外部,它将崩溃并且不会有任何警告。例如public T[] toArray() return array; @newacct:我查过了,你是对的。然而,它仍然让我感到疑惑。构造函数中的强制转换不会引发异常。将任何类型放入 Object[] 中是合法的。在这种情况下,我认为不需要抛出异常 不同的数组类型在运行时是不同的类,所以如果你创建一个Object[],你不能将它转换成String[]。构造函数中没有真正的强制转换,因为T 在类的范围内被删除。相反,每次有人从T 类型的类中得到一些东西时,编译器都会在那里插入一个他们期望的类型的转换。例如当有人调用HashTable&lt;String&gt; foo = ...; String bar = foo.get("baz"); 时被擦除为HashTable foo = ...; String bar = (String)foo.get("baz"); 这就是调用代码中发生异常的原因。

以上是关于Java泛型错误[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Java:泛型参数上带有.class的泛型方法[重复]

Java泛型中的“超级”和“扩展”有啥区别[重复]

在Java中实例化一个泛型类[重复]

C#与Java泛型[重复]

Java 泛型

保存ArrayLists时由泛型引起的Java编译器警告[重复]