繁体   English   中英

无法创建通用数组

[英]Cannot create a generic array

我收到以下代码的错误“无法创建通用数组”:

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;
        }
    }

    }

我确实知道我们无法创建泛型类型或采用类型参数的类型的数组。 但是,在我的代码中,Entry类不是通用类型。 我在俯视什么吗?

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

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),因为正如您所说,您已经屏蔽了外部类的原始KV ,这意味着您现在无法访问它们

        void method(T tt){
            t = tt;
        }

方法不能编译,因为T从内部类不一样T从外部类。 因此, Entry不再是MapImpl<K,V>.Entry而是MapImpl.Entry<K,V> ,当您将其编写为

new Entry[...]

您明确地将其设为可以使用的原始类型(在声明private Entry[] entries时出现有关原始类型的编译警告)

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

编辑:我的意思是

 private static class Entry<K, V>

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

entries = new MapImpl.Entry[DEFAULT_CAPACITY];

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

请尝试以下代码

package com.vibhs.stack.overflow.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<K,V> {
    private K key;
    private V value;

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM