以下代码无法编译:
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的代码
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 :(得分:12)
我认为你并不了解泛型如何运作。
MyList<?> list = new MyList<Object>();
Class<String> clazz= list.get(0);
此代码段无法编译,因为您告诉编译器list
将保留Class<Object>
类型 - 然后在下一行中您希望它返回{{1} }。 Java中的通用系统无法像你想象的那样转换基于继承的泛型使用的类型。
如果您希望Class<String>
持有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);
返回的Object
强制转换为您正在使用的声明类型(这一直是这种情况)
get()
答案 1 :(得分: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>> {
}
}
答案 2 :(得分:1)
在您的示例中,MyList是您要更新的旧代码以支持泛型?如果是这样,我的列表应该包含哪种类型的对象?
正如其他地方提到的那样,编译错误是有效的。这是因为正在访问原始列表而不将其转换为类。因此,代码试图将Object分配给Class的引用。它相当于:
Object o = new Object();
Class c = o;
哪根本无法编译。此外,为了充分利用泛型,你应该支持Class&lt;?&gt;而不是Class。
答案 3 :(得分:0)
在您的示例中,第二个示例不起作用,因为您没有使用泛型,因此这意味着get()方法将返回一个Object,您需要将其强制转换为Class。如果没有为MyList指定类型:
MyList list2 = new MyList();
然后你失去了Generics的优点,你需要在调用get()方法时强制转换对象,就像在好日子里一样。
答案 4 :(得分:-1)
你试过了吗?
Class clazz2 = list2.get(0).getClass();
阅读: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#getClass()