Suppose I have the following pattern repeating often in my code:
class A<T> {
@Inject
public A(List<T> list) {
// code
}
}
I want to bind all List<T>
to ArrayList<T>
.
I know I can use TypeLiteral
s to bind an explicit raw type, e.g., List<String>
, but is there anyway to do this for all types?
Basically, this code should not fail because I didn't bind List explicitly:
injector.getInstance(new Key<A<Integer>>(){});
This is not possible in Guice. Internally Guice is little more than a HashMap<Key, Provider<?>>
, where a Key
represents an optional binding annotation and a single fully-qualified type. To match a "pattern" of types would require a Key to behave more like a predicate, which would require a very different architecture and which would make binding lookup much slower.
Furthermore, though you may be using List for a simple example, remember that Guice bindings are better reserved for equivalent implementations that are likely to vary in production or tests. In addition to having very different algorithm-specific performance characteristics, List implementations vary in their ability to handle null
items, and once you've picked an ideal list implementation for a given algorithm you're unlikely to need to change it—especially in an application-wide configuration.
If you do want to be able to vary your generic implementations with Guice-style configuration, create a very small factory like ListFactory
:
public class ListFactory {
public <T> List<T> createFooBarList() { return new ArrayList<T>(); }
public <T> List<T> createSomeOtherList() { return new LinkedList<T>(); }
}
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