Generics are at once the most welcome, easy to understand and most perplexing feature added to Java since… well ever! I couldn’t imagine life without them, but like anything in type theory they are at times confoundingly opaque. Here are some all-too-common misconceptions about Java Generics and Generic types in general:

  • Set<Child> is a subtype of Set<Parent>

This is an unfortunate misapprehension brought on by the rather strange fact that Child[] is a subtype of Parent[].

  • Type erasure means there is no real difference between Set<T>, Set or Set<E>

Type erasure means there is no way to enforce the difference between them at runtime.

  • Set<?> is equal to Set<?>

This one came up in the Guice list recently: why can’t we declare a variable as Set<?> and then bind it to some implementation that Set<?> accepts?

The answer is that Set<?> is a wildcard type. In other words, it is a query on all types that match Set<?>. Like Set<Object>, Set<Socket>, Set<BuckRogers>, and everything else besides. 

Java cannot close over the scope of all possible bindings to any give Set<?>. In other words, because Set<?> can be any Set type, Java cannot assume that it is any one Set type. Therefore you cannot bind Set<?> to any particular Set.

  • The same goes for Set<? extends Thing>

This is a special kind of wildcard known as a bounded wildcard. In essence, a wildcard is a closure over the global scope of the program. If such a closure were possible, we could bind wildcards correctly. But this is not doable without the source code to everything (aka global compilation =)

  • Type reification would have let us do cool things like new T();

No, it would not.

  • Guice can @Inject List<T> if I bind all possible List<T>’s used in my program

Type erasure means that Guice has no idea what the witness of T was, when bound. 



No Responses Yet to “Clearing up misconceptions about Generics”  

  1. No Comments Yet

Leave a Reply