What are Reified Generics? How do they solve Type Erasure problems and why can't they be added without major changes?

JavaGenericsCollectionsJvmReification

Java Problem Overview


I've read Neal Gafter's blog on the subject and am still unclear on a number of points.

Why is it not possible to create implementations of the Collections API that preserve type information given the current state of Java, the JVM and existing collections API? Couldn't these replace the existing implementations in a future version of Java in a way where backwards compatibility is preserved?

As an example:

List<T> list = REIList<T>(T.Class);

Where REIList is something like this:

public REIList<T>() implements List {
  private Object o;
  private Class klass;

  public REIList(Object o) {
    this.o = o;
    klass = o.getClass();
  }
... the rest of the list implementation ...

And the methods use Object o and Class klass to get the type information.

Why would preserving generic class information require language changes rather than just a JVM implementation change?

What am I not understanding?

Java Solutions


Solution 1 - Java

The whole point is that reified generics have support in the compiler for preserving type information, whereas type erased generics don't. AFAIK, the whole point of having type erasure in the first place was to enable backwards compatibility (e.g. lower versioned JVMs could still understand generic classes).

You can explicitly add the type information in the implementation, as you have above, but that requires additional code every time the list is used, and is pretty messy in my opinion. Also, in this case, you still don't have runtime type checking for all of the list methods unless you add the checks yourself, however reified generics will ensure the runtime types.

Solution 2 - Java

Contrary to beliefs of majority of Java developers, it is possible to keep compile-time type information and retrieve this information at runtime, despite in a very restricted way. In other words: Java does provide reified generics in a very restricted way.

Regarding type erasure

Notice that, at compile-time, the compiler has full type information available but this information is intentionally dropped in general when the binary code is generated, in a process known as type erasure. This is done this way due to compatibility issues: The intention of language designers was providing full source code compatibility and full binary code compatibility between versions of the platform. If it was implemented differently, you would have to recompile your legacy applications when you migrate to newer versions of the platform. The way it was done, all method signatures are preserved (source code compatibility) and you don't need to recompile anything (binary compatibility).

Regarding reified generics in Java

If you need to keep compile-time type information, you need to employ anonymous classes. The point is: in the very special case of anonymous classes, it is possible to retrieve full compile-time type information at runtime which, in other words means: reified generics.

I've written an article about this subject:

http://rgomes-info.blogspot.co.uk/2013/12/using-typetokens-to-retrieve-generic.html

In the article, I describe how our users reacted to the technique. In a nutshell, this is an obscure subject and the technique (or the pattern, if you prefer) looks extraneous to majority of Java developers.

Sample code

The article I've mentioned above has links to source code which exercises the idea.

Solution 3 - Java

IIRC (and based on the link), Java generics are just syntactic sugar for the existing technique of using an Object collection and casting back and forth. It's safer and simpler using the Java generics, since the compiler can do the checks for you to verify that you maintain compile-time type safety. Run time, however, is an entirely different problem.

.NET generics, on the other hand, actually create new types - a List<String> in C# is a different type than a List<Int>. In Java, under the covers, they are the same thing - a List<Object>. This means that if you have one of each, you can't look at them at run time and see what they were declared as - only what they are now.

The reified generics would change that, giving Java developers the same capabilities that exist now in .NET.

Solution 4 - Java

I'm no expert on the subject, but as I understand it the type information is lost at compile time. Unlike in C++, Java does not use a template system, type safety is achieved entirely through the compiler. At runtime, a List is actually a List, always.

So my take is that a change in the language specification is required due to the fact that the type information is not available to the JVM because it isn't there.

Solution 5 - Java

Simple explanation I can think of - they deliberately chose simplicity over code bloat, because of erasure after code is compiled there is only one implementation of a generic class and its subtypes.

C++ on the other hand create separate version of code for each implementation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsalView Question on Stackoverflow
Solution 1 - JavaghemptonView Answer on Stackoverflow
Solution 2 - JavaRichard GomesView Answer on Stackoverflow
Solution 3 - JavaHarper ShelbyView Answer on Stackoverflow
Solution 4 - Javan3rdView Answer on Stackoverflow
Solution 5 - JavaVinKrishView Answer on Stackoverflow