2008-11-13 50 views
1

下面的代码无法编译:引入泛型的Java代码,而不破坏构建

public class GenericsTest {  
    public static void main(String[] args) { 
     MyList<?> list = new MyList<Object>(); 
     Class<?> clazz = list.get(0); 

     // Does not compile with reason 
     // "Type mismatch: cannot convert from Object to Class" 
     MyList list2 = new MyList(); 
     Class clazz2 = list2.get(0); 
    } 
    static class MyList<T> extends ArrayList<Class<T>> { 
    } 
} 

我想这样做是为了引入泛型的旧代码,而不破坏构建。

这是编译器(eclipse和javac)中的错误还是我在这里丢失了一些东西?将泛型引入MyList还有什么其他可能性?

编辑

对于澄清:

我有泛型类

public class MyList extends ArrayList<MyObject> {} 

public class MyObject {} 

,并使用MYLIST

代码3210
MyList list = new MyList(); 
... 
MyObject o = list.get(0); 
发展中,我看到我要介绍的泛型MYOBJECT

public class MyObject<T> {} 

,现在我想有MYLIST这个新的通用啄以及

public class MyList<T> extends ArrayList<MyObject<T>> {} 

期间

现在但这并突破我的构建。有趣的是

public class MyList<T> extends ArrayList<MyObject<T>> { 
    public MyObject<T> get(int i) { 
     return super.get(i); 
    } 
} 

将使旧的代码

MyList list = new MyList(); 
... 
MyObject o = list.get(0); 

编译。

好的,似乎当我引入这个泛型时,我将不得不将所有对MyList的调用改为泛型。我希望旧代码只引入警告而不是错误。

+0

如果您提供编译错误以及代码,这将有所帮助。 – Herms 2008-11-13 16:34:27

+0

编译错误在示例中的注释中。 – 2008-11-13 17:00:54

回答

12

我觉得你根本不了解仿制药相当如何工作。

MyList<?> list = new MyList<Object>(); 
Class<String> clazz= list.get(0); 

这段代码不能编译,因为你是在告诉list将要举办Class<Object>类型的编译器 - 然后在下一行你期望它返回你一个Class<String>。 Java中的通用系统无法像您认为的那样将基于继承的泛型转换为类型。

如果您希望list拥有Class<String>,那么您需要将其声明为 - 或者,如果您希望它能够容纳任何类型,则不能在没有强制转换的情况下执行第二行。

MyList<String> list = new MyList<String>(); 
Class<String> clazz = list.get(0); 

MyList<?> list = new MyList<Object>(); 
//generates a warning about an unchecked cast 
Class<String> clazz = (Class<String>) list.get(0); 

的第二代码片段无法正常工作,因为当你使用原始的类型,你仍然需要通过get()投返回Object您所使用声明的类型(这一直是这种情况)。

MyList list2 = new MyList(); 
Class clazz2 = (Class) list2.get(0); 
+0

我觉得你还没有看到类MyList的声明在最后:static class MyList extends ArrayList >。有定义,MyList 需要类 -Objects。 – Mnementh 2008-11-13 16:39:35

1

我没有在这台机器上的编译器,但这应该工作。

public class GenericsTest {  
    public static void main(String[] args) { 
     MyList<Object> list = new MyList<Object>(); 
     Class<?> clazz= list.get(0); 

    } 


    static class MyList<T> extends ArrayList<Class<? extends T>> { 
    } 
} 
1

在您的例子是MYLIST要更新到支持泛型的旧代码?如果是这样,我的列表应该包含什么类型的对象?

正如在别处提到的那样,编译错误是有效的。这是由于原始列表正在被访问而没有被转换为Class。因此,代码试图将一个对象分配给一个类的引用。它相当于这样:

Object o = new Object(); 
Class c = o; 

哪个根本无法编译。此外,要充分利用仿制药,您应该赞成类<? >而不是Class。

0

在您的示例中,第二个示例不起作用,因为您没有使用泛型,因此它意味着get()方法将返回一个Object,并且您需要将其转换为Class。当您没有为您的MyList指定类型时:

MyList list2 = new MyList();

然后,你正在失去泛型优点,你需要在调用get()方法时抛出对象,就像在良好的日子里一样。