与泛型和类一起苦苦挣扎

时间:2009-07-09 06:55:03

标签: java arrays generics

我总是在苦恼中苦苦挣扎。我不知道为什么这会让我发疯。我有几次老问题。

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<?>[] {

这个解决方案并不令人满意,因为你无法轻易投射。

所以我的问题是:如何解决这个问题?我脑子里的结是哪里的?

6 个答案:

答案 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);
}

它相当冗长但具有完全不变的优点,因此更容易推理。