It seems to me that Guice implementation is doing some very tricky things when dealing with generics. It looks like it knows at runtime about generic types used at compile time. Let's see a simple example:
@Inject
public void Bar(Provider<Foo> genericInjector){
...
At runtime Guice will inject a correct implementation of Provider
here (i.e. the one that provides Foo
instances). But from what I know, generic types are erased at runtime (see: Type Erasure ). So all that Guice really sees at runtime is:
@Inject
public void Bar(Provider genericInjector){
....
So how is it possible that Guice knows which implementation of Provider
to inject?
No, type erasure doesn't erase everything. You can still get the types of fields, parameters etc. The Provider<Foo>
information is still present at execution time. See Method.getGenericParameterTypes
for example.
What isn't preserved is the type information about specific objects. For example, if I write:
List<String> list = new ArrayList<String>();
showType(list);
...
public static void showType(List<?> list)
{
// ???
}
There's no way that can work out that it's an ArrayList<String>
because the object doesn't have that information any more.
See the Java Generics FAQ for a lot more information.
It is a common misconception that the way type erasure works is that the compiler essentially removes angle brackets and what's inside them and then acts as if the source was Java 1.4. This is not the case.
Generic parameters don't get erased from method signatures – method signatures are "compile-time". Generic parameters don't exist in "runtime" constructs – you can't tell what type parameters a given object was instantiated with.
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