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

2022-09-03 14:37:13

我知道你不能创建一个泛型类型的数组,相反,你必须诉诸黑客。(鉴于Java支持通用数组,只是不支持它们的创建,我不清楚为什么黑客比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);

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


我看到了来自内部类的泛型数组创建编译错误,但恕我直言,这里的解决方案更糟。


答案 1

请执行下列操作:

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

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


答案 2

你需要意识到的是,你的情况与你描述的第一个情况是一样的。

Inner是 的非静态内部类,是泛型类。这意味着在类型参数的范围内,简单地编写是 .即,它可能看起来不是它,而只是一个参数化类型,就像 一样,因为外部类的类型参数隐式地成为内部类的类型参数。这两个问题的解决方案是相同的。OuterInnerInnerOuter<E>.InnerInnerMap.Entry<K, V>E

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

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

还有另一种方法可以创建泛型类型的数组,而无需使用原始类型 - 使用通配符类型,即.对于我们的情况,等效项将是 。演员阵容:new Map.Entry<?, ?>[numEntries];new Outer<?>.Inner[16];

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