无法创建通用数组

时间:2015-05-04 11:31:30

标签: java generics

我收到错误"无法创建通用数组"对于以下代码:

public class MapImpl<K, V> {
    private static int DEFAULT_CAPACITY = 16;

    private int size;
    // array holding the entries of the map
    private Entry[] entries;

    public MapImpl() {
        entries = new Entry[DEFAULT_CAPACITY]; // error at this line: Cannot create a generic array of MapImpl<K,V>.Entry
    }

    // represents an entry in the map
    private class Entry {
        private K key;
        private V value;

        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }

令人惊讶的是,这很好用:

public class MapImpl<K, V> {
    private static int DEFAULT_CAPACITY = 16;

    private int size;
    // array holding the entries of the map
    private Entry<K, V>[] entries;

    public MapImpl() {
        entries = new Entry[DEFAULT_CAPACITY];
    }

    // represents an entry in the map
    private class Entry<K, V> {
        private K key;
        private V value;
//but here K and V are being hidden.
        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }

    }
  

我知道我们无法创建泛型类型或a   采用类型参数的类型。但是,在我的代码中这是Entry类   不属于通用类型。我忽略了什么吗?

5 个答案:

答案 0 :(得分:4)

问题在于,非静态嵌套类可以访问其外部类的所有成员,其中包括有关外部类中使用的泛型类型的信息,例如

class Outer<T>{
    private T t;
    class Inner{
        void method(T tt){//we can use same type T as used in outer class
            t = tt;
        }
    }
}

所以实际上Inner类类型更像是Outer<T>.Inner,它使得它的形式为泛型类型,并且由于类型擦除会阻止数组能够从泛型类型创建数组测试添加的元素是否有效。

在这种情况下,最常见的解决方案是使用集合而不是像List<OurType>这样的数组。

但是,如果你真的只想拥有数组,那么其他可能的解决方案(但你应该尽量避免它)是使用原始类型,所以而不是

new Entry[DEFAULT_CAPACITY];

相当于

new MapImpl<K, V>.Entry[DEFAULT_CAPACITY];

你可以使用

new MapImpl.Entry[DEFAULT_CAPACITY];
//         ^no generic type -> it is raw type

解决方案

private class Entry<K, V> {
    private K key;
    private V value;
//but here K and V are being hidden.
    public Entry(K key, V value) {
        this.key = key;
        this.value = value;
    }
}

工作 可能 (我找不到任何描述此问题的相关JLS),因为正如您所说,您已隐藏原始K和{{1}来自外部类,这意味着您无法访问它们,现在

V

方法不会编译,因为内部类的 void method(T tt){ t = tt; } 与外部类的T不同。因此,T不再是Entry而是MapImpl<K,V>.Entry,当您将其写为

MapImpl.Entry<K,V>

您明确地将其设置为原始类型(当您声明new Entry[...] 时有关于rawtypes的编译警告)

答案 1 :(得分:2)

Entry类声明为静态。目前它不是静态的,因此它隐式链接到MapImpl实例及其泛型参数。

编辑:我的意思是

 private static class Entry<K, V>

答案 2 :(得分:2)

由于Entry是泛型类MapImpl的内部类,因此它也由KV进行参数化。要创建数组,您必须使用原始类型创建它:

entries = new MapImpl.Entry[DEFAULT_CAPACITY];

答案 3 :(得分:0)

这是因为Java的数组(与泛型不同)在运行时包含有关其组件类型的信息。因此,在创建阵列时必须知道组件类型。由于您不知道运行时KV是什么,因此无法创建数组。

答案 4 :(得分:0)

尝试以下代码

###\.###\.###\.###