Martin
Martin

Reputation: 3753

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?

Upvotes: 7

Views: 290

Answers (1)

gustafc
gustafc

Reputation: 28885

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.

Upvotes: 6

Related Questions