Is Erasure Ruining Java?

Java used to be a simply typed system. This led to lots of type errors but there was a sort of consistency. Then came Generics which were supposed to give us extra type safety and in simple cases do. However, as soon as you try to do anything half way sophisticated, erasure hits you over the head .

At compile time X<A> and X<B> are different types. This is good and very consistent with type theory. However at run time X<A> and X<B> are the same type -- they are both just X because of the erasure system Sun invented. Now this wouldn't be a problem if there was only static typing but there isn't, Java has dynamic type checking and casting -- not full dynamic typing but enough to cause real problems for the programming model. For example, If I define a generic type with value equality rather than identity equality then:

assertTrue ( ( new X ( ) ).equals ( new X ( ) ) ) ;

does not fail as a run time statement which is almost certainly totally surprising to the reader of the code since they are looking at the statement and thinking in compile time types. The conflict arises here because equals has to be written with a parameter of type Object to get overriding.

Then of course, we have the compile time / run time conflict associated with casting. For example:

X xa = (X) p ;

causes a compile time warning since the cast is actually (X) p due to erasure. However if you write:

X xa = (X) p ;

the compiler issues an error because of the inconsistency between the use of a parameterized type and the raw type. So Java has a built in conflict and it appears not to be going away in the near future.

I have other examples that get worse but they are too large to put up here.

Sun introduced this wonderful new technology of type erasure in the name of backward compatibility and not changing the JVM. But then they went and changed the JVM anyway but not by introducing the small changes that would allow run time types to include type parameters -- unlike C# which got it right from the outset. Like C#, Python and Ruby do not have this problem. Groovy avoids the problem by ignoring Java 5.0 and sticking with Java 1.4, at the expense of having all the problems of the underlying Java type system. However, it is a totally dynamic language like Python and Ruby so the mindset is different.

So my (bold) assertion is that Java is being ruined by the type erasure system and the programmer confusion it causes. Sun should alter the JVM to implement run time parameterized types properly. I don't see why this wasn't done for Java 5.0 -- it is clear that an extension to the JVM can be made that has no problem executing already compiled classes fine.

Or does anyone have a way of thinking about the Java type system and erasure that creates a nice consistent mental model?

Copyright © 2005–2020 Russel Winder - Creative Commons License BY-NC-ND 4.0