我的代码如下
package com.foo;
public class TestComposition {
public static void main(String[] args) {
try {
Class<Foo> fooClass =
(Class<Foo>) Class.forName("Foo");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
'try'块中的分配会产生警告
Type safety: Unchecked cast from Class<capture#1-of ?> to
Class<Foo>
为什么会这样?
答案 0 :(得分:33)
首先,如果你知道确切的类,那么你不需要Class.forName
。 Foo.class
会这样做。 (在J2SE 5.0之前,Foo.class
实际编译为执行Class.forName("Foo")
,然后在静态中缓存它。)
你可能想要的是:
Class<? extends Foo> fooClass =
(Class<? extends Foo>) Class.forName("MyFoo");
(当我说想要时,演员,特别是反思都是邪恶的。)
碰巧,你有一个合适的方法来“安全地”进行演员(假设Foo
本身不是通用的)。安全,因为不提供对不兼容对象的引用,而不是没有错误或没有意外的异常。
Class<? extends Foo> fooClass =
Class.forName("MyFoo").asSubclass(Foo.class);
答案 1 :(得分:7)
嗯,首先让我们清楚问题出在哪里 - 它就在演员阵容中。这是一个较短的例子:
public class Test {
public static void main(String[] args) throws Exception {
Object x = (Class<Test>) Class.forName("Test");
}
}
这仍然有同样的问题。问题是演员实际上并没有测试任何东西 - 因为演员表将被有效地转换为原始Class
类型。对于Class<T>
,它稍微有点令人惊讶,因为实际上对象确实知道所涉及的类,但考虑类似的情况:
List<?> list = ... get list from somewhere;
List<String> stringList = (List<String>) list;
该演员不会检查真的是List<String>
,因为类型删除导致该信息丢失。
现在在你的情况下,实际上有一个相当简单的解决方案 - 如果你在编译时知道类名,只需使用:
Class<Foo> fooClass = Foo.class;
如果你能提供一个更实际的例子不的情况,我们可以帮助你确定最合适的选择。
答案 2 :(得分:2)
运行时系统不了解泛型,因此它只能检查某些类型为Class
的内容,而不是Class<Test>
类型。这就是警告的内容。
特别为Class
类添加了一个方法以避免此警告。您可以使用它而不是自己投射:http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#asSubclass(java.lang.Class)
答案 3 :(得分:1)
如果您知道确切的类,则不需要使用Class.forName
Class<Foo> fooClass = Foo.class;
只有在您不知道类型时才这样做才有意义。