I was recently confounded by a something unexpected in Java’s type-erasure. Consider the following snippets:
It turns out that all generic type information is erased from an instance of a raw type - including all instance methods and non-static fields that have nothing to do with the type parameter declared in the class declaration. In the example above,
issue.list() returns a raw
List from which you can’t extract a
Getting around this limitation depends on your context. If the calling code has the option of defining the type parameter at runtime, then the fix is as easy as
final Issue<?> issue = new Issue<>(); final String s = issue.list().get(0);. My situation was different though: due to an internal implementation detail, my interface’s generic type declaration leaked out into its public API, even though it was never my intention for the calling code to be able to provide implementations of my interface. My final solution was getting rid of the generic type declaration entirely, albeit at the cost of a less-than-perfect separation of concerns in my internal implementation.
Why does Java behave this way? “Backwards-compatibility issues”. ¯\_(ツ)_/¯