Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java8 Supplier interface to provide the proper typed instance

Tags:

java

generics

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!

like image 522
Richard Sand Avatar asked Nov 08 '22 07:11

Richard Sand


1 Answers

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).

like image 90
Jacob G. Avatar answered Nov 14 '22 22:11

Jacob G.