调用'Class.forName'时未经检查的强制转换警告

时间:2011-07-07 11:10:12

标签: java casting compiler-warnings

我的代码如下

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>

为什么会这样?

4 个答案:

答案 0 :(得分:33)

首先,如果你知道确切的类,那么你不需要Class.forNameFoo.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;

只有在您不知道类型时才这样做才有意义。