How do I call Class.forName() when the result is a generic type? Usually I can use asSubclass(), but here the only way I see to do it is a cast, which kindof sticks out & bugs me when everything else is nicely typed with generics.
The scenario goes something like this:
There is a .jar with one entry point main class that has a main(). It takes an option of a classname (and some others, irrelevant here). The class given implements Callable<Integer>. This class is loaded, inited & launched.
Here is an example of what I need:
Class<? extends Callable<Integer>> clazz = (Class<? extends Callable<Integer>>) Class.forName(options.valueOf(className)).asSubclass(Callable.class);
Is there any way to get rid of that cast?
Using SE6.
First you probably want a full generic
ClassThen the java type system has no problem with
How can we get
classCI? We can cheat by unchecked castThis is inherently unsafe. There must be external forces to make sure the
classNamereally is aCallable<Integer>. For example if it’s aCallable<String>, the program runs through all the casts without any problem, and it only blows up much later whenInteger call()is invoked, and the error message will be very misleading.It’s ok if a cast cannot be analyzed statically to succeed:
as long as an exception is immediately thrown when the cast fails at runtime.
To be type safe, we must proactively check the generic type of the
classNameWe are justified to suppress “unchecked” here, because the implementation checks to make sure that if the
classNamedoesn’t really denote a class implementingCallable<Integer>, it immediately throws an exception right there. Our cast is “checked”, and the program is type safe.