Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unchecked cast when bounding the generic parameter to Class<?>

I have some code that takes an externally provided class name, and needs to construct an instance that implements some interface, lets call it Foo.

As part of this process, I'd like to have the following function:

private static Class<? extends Foo> fooFromClassName(String name) throws ClassNotFoundException {
    return (Class<? extends Foo>) Class.forName(name);
}

This obviously results in an unchecked warning, as it is genuinely unsafe - the caller may have requested "java.lang.Long" for all we know. I'd ultimately like this method to guarantee that if it doesn't throw, then the returned Class represents a Foo implementation.

My current best solution is this:

private static Class<? extends Foo> fooFromClassName(String name) throws ClassNotFoundException {
    Class<?> impl = Class.forName(name);
    if (Foo.class.isAssignableFrom(impl)) {
        @SuppressWarnings("unchecked")
        Class<? extends Foo> foo = (Class<? extends Foo>) impl;
        return foo;
    } else {
        // Throw something - ClassCastException perhaps.
    }
}

Is there a better way of doing this? Is there some way of doing that doesn't require explicit suppression of the warning?

like image 775
Martin Avatar asked Sep 21 '12 01:09

Martin


1 Answers

Class.asSubclass:

private static Class<? extends Foo> fooFromClassName(String name) throws ... {
    return Class.forName(name).asSubclass(Foo.class);
}

If the requested class isn't a subclass of Foo (or Foo itself), you'll get a ClassCastException. In other words, it does pretty much the same thing your solution does.

like image 158
gustafc Avatar answered Jan 07 '23 13:01

gustafc