How can I use Java8 Supplier interface to rewrite this factory method to provide the proper typed instance?
I've a simple interface that extends Map:
public interface Thingy<K, V> extends Map<K, V> {}
Then I have a ThingyFactory class, which contains a list of all of the implementation classnames of Thingy:
public final class ThingyFactory {
Map<String, Class<Thingy<?, ?>>> thingyclasses = new ConcurrentHashMap<>();
.....
@SuppressWarnings("unchecked")
public <K, V> Thingy<K, V> getInstance(String classname) throws ThingyException {
Thingy<K, V> thingy;
try {
thingy = (Thingy<K, V>) thingyclasses.get(classname).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new ThingyException("Something bad happened: ", e.toString());
}
return thingy;
}
}
I'm pretty sure that I can do this elegantly and w/o the SuppressWarnings and classloader using the Supplier interface but I can't seem to get the pattern quite right. Any guidance appreciated!
Because you're using wildcards as the generic type of Thingy
within thingyclasses
, you're essentially saying: The types of Thingy
can be anything; however, this prohibits the compiler from inferring anything about the type, hence why you require an explicit cast. You can use Supplier
to improve it slightly, but you'll still have the warning regarding an unchecked cast:
class ThingyFactory {
private Map<String, Supplier<Thingy<?, ?>>> providers = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
public <K, V> Supplier<Thingy<K, V>> getInstance(String classname) {
return () -> (Thingy<K, V>) providers.get(classname);
}
}
If you want it to be type-safe, you'll need to redesign it entirely and only use wildcards if the compiler is able to infer the type(s).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With