2009-07-09 62 views
3

我一直在用泛型挣扎。我不知道为什么这让我发疯。我有几个老问题。与仿制药和类奋斗

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

此解决方案不令人满意,因为您无法轻松投射。

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

回答

8

这是因为java不支持通用数组的创建。泛型最适合于Collections。所以你可以使用ArrayList来解决你的问题:

 ArrayList<Class<? extends Father>> myNiceClasses = new ArrayList<Class<? extends Father>>(); 
     myNiceClasses.add(Child1.class); 
     myNiceClasses.add(Child2.class); 
+0

+1。对Collections使用泛型,而不是数组。 – seanmonstar 2009-07-09 07:56:28

4

什么quant_dev的连接线的意思是,通用阵列不能被创建,因为他们无法保证类型安全。泛型所不允许的数组中的事物最终会结束。我知道无论如何干净的方式是:

private static Class<? extends Father>[] myNiceClasses = 
     (Class<? extends Father>[]) new Class<?>[] {}; 
1

泛型和数组是最好的避免的组合。编译器不喜欢你创建一个通用数组的事实是Java Generics除了语言之外的另一个事实,偶尔你可以看到这个连接。另一个例子是例外,你不能将这些与泛型结合起来。

我建议在这种情况下避免数组。改为使用通用列表。

1

这是由于所谓的类型擦除。 Java编译器会在编译过程中清除所有通用信息。 (这是因为泛型是语言的后添加,Sun决定不修改JVM以实现向后兼容性,这意味着该语言知道泛型,但JVM不知道)

由于JVM在运行时不知道泛型类型,它不能实例化该泛型类型的数组。在你的情况下,它能做的最好的是实例化一个原始类型的数组Class

在这样的例子中,使用完全支持泛型的集合框架要好得多。总结:泛型和数组不混合。

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

这是相当冗长,但有被完全不变,因此优势更容易推理。