Home > other >  Java compiler forcing raw use of paramatized interface
Java compiler forcing raw use of paramatized interface

Time:02-14

I'm trying to implement a generic interface with concrete types, but the java compiler is forcing me to instantiate it as raw. This is a mock-up of my code:

public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("thing", "extra");
    Worker<String, String> worker = new Worker<>();
    worker.execute(map);
}

public class Worker<K, V> {
    public void execute(Map<K, V> map) {
        IDao<K, V> dao = new Dao();
        dao.doThing(map);
    }
}

public interface IDao<K, V> {
    void doThing(Map<K, V> map);
}

public class Dao implements IDao<String, String> {
    public void doThing(Map<String, String> map) {
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String newKey = key.toUpperCase();
            System.out.println(newKey   " "   entry.getValue());
        }
    }
}

This code works as expected if I change IDao<K, V> dao = new Dao(); to IDao dao = new Dao(), but this isn't good practice and I'd like to avoid it. I don't understand why it's illegal to declare the types at instantiation like this.

CodePudding user response:

This...

public class Worker<K, V> {
    public void execute(Map<K, V> map) {
        IDao<K, V> dao = new Dao();
        dao.doThing(map);
    }
}

seems wrong to me.

The Worker class allows for generic key/value parameters for the Map, but, you're instantiating an instance of Dao which is constrained to <String, String>. This seems like a basic violation of the contract.

Personally, I might change this so that the instance of IDao is injected into the worker, for example...

public static class Worker<K, V> {
    
    private IDao<K, V> dao;

    public Worker(IDao<K, V> dao) {
        this.dao = dao;
    }

    public void execute(Map<K, V> map) {
        dao.doThing(map);
    }
}

nb: This could be an abstract factory, which had a abstract method something like abstract protected IDao<K, V> getDao(); and then you'd have to provide some kind concrete implementation to support it, but it's basically boiling down to the same thing

Then you'd simply be able to call it doing something like...

Map<String, String> map = new HashMap<>();
map.put("thing", "extra");
Worker<String, String> worker = new Worker<>(new Dao());
worker.execute(map);

Of course, if you didn't want to do that, then you'd have to remove the generic constraints for Worker and require that any caller pass it a Map constrained to <String, String>

public static class Worker {
    public void execute(Map<String, String> map) {
        IDao<String, String> dao = new Dao();
        dao.doThing(map);
    }
}

But now, where's the benefit?

  • Related