Unchecked Cast Warning when calling 'Class.forName'

纵然是瞬间 提交于 2019-12-08 23:55:12

问题


My code is as follows

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

The assignment within the 'try' block results in a warning stating

Type safety: Unchecked cast from Class<capture#1-of ?> to 
     Class<Foo>

Why is this?


回答1:


Well, to start with let's be clear where the problem is - it's in the cast itself. Here's a shorter example:

public class Test {    
    public static void main(String[] args) throws Exception {
        Object x = (Class<Test>) Class.forName("Test");
    }
}

This still has the same problem. The issue is that the cast isn't actually going to test anything - because the cast will be effectively converted to the raw Class type. For Class<T> it's slightly more surprising because in reality the object does know the class involved, but consider a similar situation:

List<?> list = ... get list from somewhere;
List<String> stringList = (List<String>) list;

That cast isn't going to check that it's really a List<String>, because that information is lost due to type erasure.

Now in your case, there's actually a rather simpler solution - if you know the class name at compile-time anyway, just use:

Class<Foo> fooClass = Foo.class;

If you can provide a more realistic example where that's not the case, we can help you determine the most appropriate alternative.




回答2:


Firstly, if you know the exact class then you don't need Class.forName. Foo.class will do. (Prior to J2SE 5.0, Foo.class actually compiled to doing Class.forName("Foo") and then caching it in a static.)

What you probably want is something like:

Class<? extends Foo> fooClass =
    (Class<? extends Foo>) Class.forName("MyFoo");

(When I say want, casts and particularly reflection are evil.)

As it happens, you there is an appropriate method to do the cast "safely" (assuming Foo is not itself generic). Safely as in not providing a reference to an incompatible object, not as in there are no bug or no unexpected exception.

Class<? extends Foo> fooClass =
    Class.forName("MyFoo").asSubclass(Foo.class);



回答3:


The runtime system has no knowledge about generics and therfore it can only check that something is of type Class, not if it is of type Class<Test>. That is what the warning is about.

A method has specifically been added to the Class class to avoid this warning. You can use this instead of casting yourself: http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#asSubclass(java.lang.Class)




回答4:


If you knew the exact class, you wouldn't need to use Class.forName

Class<Foo> fooClass = Foo.class;

It only makes sense to do this when you don't know the type.



来源:https://stackoverflow.com/questions/6609667/unchecked-cast-warning-when-calling-class-forname

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!