Search code examples
javareflectioncompiler-warningstype-safety

Java: properly checked class instantiation using reflection


I'm trying to use one of the simplest forms of reflection to create an instance of class:

package some.common.prefix;

public interface My {
    void configure(...);
    void process(...);
}

public class MyExample implements My {
    ... // proper implementation
}

String myClassName = "MyExample"; // read from an external file in reality

Class<? extends My> myClass =
    (Class<? extends My>) Class.forName("some.common.prefix." + myClassName);
My my = myClass.newInstance();

Typecasting unknown Class object we've got from Class.forName yields a warning:

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

I've tried using instanceof check approach:

Class<?> loadedClass = Class.forName("some.common.prefix." + myClassName);
if (myClass instanceof Class<? extends RST>) {
    Class<? extends My> myClass = (Class<? extends My>) loadedClass;
    My my = myClass.newInstance();
} else {
    throw ... // some awful exception
}

but this yields a compilation error: Cannot perform instanceof check against parameterized type Class<? extends My>. Use the form Class<?> instead since further generic type information will be erased at runtime. So I guess I can't use instanceof approach.

How do I get rid of it and how am I supposed to do it properly? Is it possible to use reflection without these warnings at all (i.e. without ignoring or supressing them)?


Solution

  • This is how you do it:

    /**
     * Create a new instance of the given class.
     * 
     * @param <T>
     *            target type
     * @param type
     *            the target type
     * @param className
     *            the class to create an instance of
     * @return the new instance
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> T newInstance(Class<? extends T> type, String className) throws
            ClassNotFoundException,
            InstantiationException,
            IllegalAccessException {
        Class<?> clazz = Class.forName(className);
        Class<? extends T> targetClass = clazz.asSubclass(type);
        T result = targetClass.newInstance();
        return result;
    }
    
    
    My my = newInstance(My.class, "some.common.prefix.MyClass");