nilesh
nilesh

Reputation: 14279

Guice nested generic type binding

I am using guice for dependency injection and wrote a provider that returns HashMap<String, HashMap<String, String>>. How do I bind HashMap.class with this provider?

I looked at this but not able to figure out how to use TypeLiteral for the HashMap value (V) in HashMap<K,V>. Therefore, I just replaced the V in <K,V> with Object. Currently my ugly binding looks like below which has obvious disadvantages. I have to get the object and cast it to HashMap<String, String>to get further values. However this works but I am looking for a better suggestion.

    binder().bind(new TypeLiteral<Map<String, Object>>() {}).toProvider(
(Class<? extends Provider<? extends Map<String, Object>>>) TestProvider.class);

Upvotes: 3

Views: 2026

Answers (1)

Jeff Bowman
Jeff Bowman

Reputation: 95614

Type literals can have their generics specified two levels deep, or as deeply as you want to go. Try this.

class TestProvider implements Provider<Map<String, Map<String, String>>> {
  @Override public Map<String, Map<String, String>> get() {
    // If you had Guava, you could just call "return Maps.newHashMap();".
    // On Java 7, you can use "return new HashMap<>();".
    return new HashMap<String, Map<String, String>>();
  }
}

class TestModule extends AbstractModule {
  @Override protected void configure() {
    bind(new TypeLiteral<Map<String, Map<String, String>>>() {})
        .toProvider(TestProvider.class);
    // or
    bind(new TypeLiteral<HashMap<String, HashMap<String, String>>>() {})
        .toProvider(HashMapTestProvider.class);
  }
}
  • Favor interfaces instead of implementations, and note that:

                          HashMap<String, HashMap<String, String>>
           can be cast to     Map<String, HashMap<String, String>>  (1)
    but cannot be cast to     Map<String,     Map<String, String>>  (2)
    

    (1) above guarantees that it only contains HashMaps while (2) can contain any map implementation.

  • You may appreciate using a Guava Table directly. It's basically a two-key map, and can create row or column maps for you as needed.

Upvotes: 3

Related Questions