我知道你不能创建一个泛型类型的数组,而是你必须求助于黑客攻击。 (鉴于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,但这里的解决方案更糟糕恕我直言。
答案 0 :(得分:8)
执行以下操作:
@SuppressWarnings("unchecked")
final Inner[] inners = (Inner[])new Outer<?>.Inner[16];
与你的第一个示例相同的是new Outer.Inner[16]
,但这将隔离未经检查的强制转换并避免原始类型。
答案 1 :(得分:5)
您需要意识到的是,您的情况与您描述的第一种情况相同。
Inner
是Outer
的非静态内部类,是一个泛型类。这意味着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 {
}
}