我总是在苦恼中苦苦挣扎。我不知道为什么这会让我发疯。我有几次老问题。
class Father {
...
}
class Child1 extends Father {
...
}
class Child2 extends Father {
...
}
public class TestClass {
private static Class<? extends Father>[] myNiceClasses = new Class<? extends Father>[] {
Child1.class,
Child2.class
}
}
不工作。编译器抱怨如下:
Cannot create a generic array of Class<? extends Father>
如果我将(有故障的)阵列线更改为
private static Class<Father>[] myNiceClasses = new Class<Father>[] {
发生相同的错误消息,但也添加了此消息:
Type mismatch: cannot convert from Class<Child1> to Class<Father>
唯一可行的版本是这一行:
private static Class<?>[] myNiceClasses = new Class<?>[] {
这个解决方案并不令人满意,因为你无法轻易投射。
所以我的问题是:如何解决这个问题?我脑子里的结是哪里的?
答案 0 :(得分:8)
这是因为java不支持通用数组创建。泛型最适合收藏。所以你可以使用ArrayList来解决你的问题:
ArrayList<Class<? extends Father>> myNiceClasses = new ArrayList<Class<? extends Father>>();
myNiceClasses.add(Child1.class);
myNiceClasses.add(Child2.class);
答案 1 :(得分:4)
quant_dev的链接线程所说的是无法创建通用数组,因为它们无法保证类型安全。您可以最终得到泛型不允许的数组中的内容。无论如何,我知道最干净的方法是:
private static Class<? extends Father>[] myNiceClasses =
(Class<? extends Father>[]) new Class<?>[] {};
答案 2 :(得分:2)
答案 3 :(得分:1)
泛型和数组是最好避免的组合。编译器不喜欢你创建一个通用数组这一事实是Java Generics是该语言的附加功能,偶尔也可以看到连接。另一个例子是Exceptions,你也不能将它们与泛型结合起来。
我建议在这种情况下避免使用数组。改为使用通用列表。
答案 4 :(得分:1)
这是由于称为类型擦除的东西。 Java编译器在编译过程中擦除所有通用信息。 (这是因为泛型是该语言的后期添加,并且Sun决定不修改JVM,以实现向后兼容性。这意味着该语言了解泛型,但JVM不知道。)
由于JVM在运行时不知道泛型类型,因此无法实例化该泛型类型的数组。在您的情况下,它可以做的最好的事情是实例化原始类型Class
的数组。
在这样的情况下,使用完全支持泛型的集合框架要好得多。
总结一下:泛型和数组不会混合。
答案 5 :(得分:0)
或者,正如amit.dev所说,您可能想要使用列表。在这种情况下,假设myNiceClasses字段应该是常量,您可以使用Collections.unmodifiableList来确保列表无法更改:
private static final List<? extends Father> myNiceClasses;
static {
ArrayList<? extends Father> l = new ArrayList<? extends Father>();
l.add(Child1.class);
l.add(Child2.class);
myNiceClasses = Collections.unmodifiableList(l);
}
它相当冗长但具有完全不变的优点,因此更容易推理。