Java不允许泛型类的内部类数组

时间:2013-12-09 16:08:38

标签: java arrays generics

我知道你不能创建一个泛型类型的数组,而是你必须求助于黑客攻击。 (鉴于Java支持通用数组,而不是它们的创建,我不清楚为什么hack比支持创建泛型数组的Java更好)

而不是写这个

Map.Entry<K, V>[] entries = new Map.Entry<K, V>[numEntries];

你必须写这个

@SuppressWarnings("unchecked")
Map.Entry<K, V>[] entries = (Map.Entry<K, V>) new Map.Entry[numEntries];

不幸的是,如果您有一个嵌套类型的泛型

,这不起作用
public class Outer<E> {
    final Inner[] inners = new Inner[16]; // Generic array creation

    class Inner {
    }
}

最好的解决方法似乎是

@SuppressWarnings("unchecked")
final Inner[] inners = (Inner[]) Array.newInstance(Inner.class, 16);

这是最“优雅”的解决方案吗?


我看了Generic Array Creation Compilation Error From Inner Class,但这里的解决方案更糟糕恕我直言。

3 个答案:

答案 0 :(得分:8)

执行以下操作:

@SuppressWarnings("unchecked")
final Inner[] inners = (Inner[])new Outer<?>.Inner[16];

与你的第一个示例相同的是new Outer.Inner[16],但这将隔离未经检查的强制转换并避免原始类型。

答案 1 :(得分:5)

您需要意识到的是,您的情况与您描述的第一种情况相同。

InnerOuter的非静态内部类,是一个泛型类。这意味着Inner属于type参数的范围,只需编写Inner就是Outer<E>.Inner的缩写。即它可能看不到它,但简单地Inner是参数化类型,就像Map.Entry<K, V>一样,因为外类的类型参数E隐式地变成内部类的类型参数。两个问题的解决方案都是一样的。

您对第一个问题的解决方案是创建一个原始类型的数组,即new Map.Entry[numEntries];。这里的原始类型是什么?正如我们已经讨论的那样,不是Inner。相反,您需要显式限定外部类型以访问原始类型:new Outer.Inner[16];。当然,您需要使用强制转换将其强制转换为所需的通用数组类型:

(Inner[])new Outer.Inner[16]

还有另一种方法可以创建泛型类型的数组,而不使用原始类型 - 使用通配类型,即new Map.Entry<?, ?>[numEntries];。我们案例的等价物是new Outer<?>.Inner[16];。演员:

(Inner[])new Outer<?>.Inner[16]

答案 2 :(得分:1)

您可以选择制作内部班级static吗?

如果可能,您可以使用标准方式创建内部类的数组:

public class Outer<E> {
    final Inner[] inners = new Inner[16]; // works

    static class Inner {
    }
}