I read a tweet today that said:
It\'s funny when Java users complain about type erasure, which is the only thing Java got right, while ignoring all th
The one thing I don't see considered here at all is that OOP's runtime polymorphism is fundamentally dependent on the reification of types at runtime. When a language whose backbone is held in place by refied types introduces a major extension to its type system and bases it on type erasure, cognitive dissonance is the inevitable outcome. This is precisely what happened to the Java community; it is why type erasure has attracted so much controversy, and ultimately why there are plans to undo it in a future release of Java. Finding something funny in that complaint of Java users betrays either an honest misunderstanding of the spirit of Java, or a consciously deprecating joke.
The claim "erasure is the only thing Java got right" implies the claim that "all languages based on dynamic dispatch against the runtime type of function argument are fundamentally flawed". Although certainly a legitimate claim on its own, and one which can even be considered as valid criticism of all OOP languages including Java, it cannot lodge itself as a pivotal point from which to evaluate and criticise features within the context of Java, where runtime polymorphism is axiomatic.
In summary, while one may validly state "type erasure is the way to go in language design", positions supporting type erasure within Java are misplaced simply because it is much, much too late for that and had already been so even at the historical moment when Oak was embraced by Sun and renamed to Java.
As to whether static typing itself is the proper direction in the design of programming languages, this fits into a much wider philosophical context of what we think constitutes the activity of programming. One school of thought, clearly deriving from the classical tradition of mathematics, sees programs as instances of one mathematical concept or other (propositions, functions, etc.), but there is an entirely different class of approaches, which see programming as a way to talk to the machine and explain what we want from it. In this view the program is a dynamic, organically growing entity, a dramatic opposite of the carefully erected aedifice of a statically typed program.
It would seem natural to regard the dynamic languages as being a step in that direction: the consistency of the program emerges from the bottom up, with no a priori constrants which would impose it in a top-down manner. This paradigm can be seen as a step towards modeling the process whereby we, the humans, become what we are through development and learning.
The reason type erasure is a good thing is that the things it makes impossible are harmful. Preventing the inspection of type arguments at runtime makes understanding and reasoning about programs easier.
An observation that I found somewhat counter-intuitive is that when function signatures are more generic, they become easier to understand. This is because the number of possible implementations is reduced. Consider a method with this signature, which we somehow know has no side effects:
public List<Integer> XXX(final List<Integer> l);
What are the possible implementations of this function? Very many. You can tell very little about what this function does. It could be reversing the input list. It could be pairing ints together, summing them and returning a list half the size. There are many other possibilities that could be imagined. Now consider:
public <T> List<T> XXX(final List<T> l);
How many implementations of this function are there? Since the implementation cannot know the type of the elements, a huge number of implementations can now be excluded: elements cannot be combined, or added to the list or filtered out, et al. We are limited to things like: identity (no change to the list), dropping elements, or reversing the list. This function is easier to reason about based on its signature alone.
Except… in Java you can always cheat the type system. Because the implementation of that generic method can use stuff like instanceof
checks and/or casts to arbitrary types, our reasoning based on the type signature can be easily rendered useless. The function could inspect the type of the elements and do any number of things based on the result. If these runtime hacks are allowed, parameterised method signatures become much less useful to us.
If Java did not have type erasure (that is, type arguments were reified at runtime) then this would simply allow more reasoning-impairing shenanigans of this kind. In the above example, the implementation can only violate the expectations set by the type signature if the list has at least one element; but if T
was reified, it could do so even if the list were empty. Reified types would just increase the (already very many) possibilities for impeding our understanding of the code.
Type erasure makes the language less "powerful". But some forms of "power" are actually harmful.
A subsequent post by the same user in the same conversation:
new T is a broken program. It is isomorphic to the claim "all propositions are true." I am not big into this.
(This was in response to a statement by another user, namely that "it seems in some situations 'new T' would be better", the idea being that new T()
is impossible due to type erasure. (This is debatable — even if T
were available at runtime, it could be an abstract class or interface, or it could be Void
, or it could lack a no-arg constructor, or its no-arg constructor could be private (e.g., because it's supposed to be a singleton class), or its no-arg constructor could specify a checked exception that the generic method does not catch or specify — but that was the premise. Regardless, it's true that without erasure you could at least write T.class.newInstance()
, which handles those issues.))
This view, that types are isomorphic to propositions, suggests that the user has a background in formal type theory. (S)he very likely does not like "dynamic types" or "runtime-types" and would prefer a Java without downcasts and instanceof
and reflection and so on. (Think of a language like Standard ML, which has a very rich (static) type system and whose dynamic semantics do not depend on any type information whatsoever.)
It's worth keeping in mind, by the way, that the user is trolling: while (s)he likely sincerely prefers (statically) typed languages, (s)he is not sincerely trying to persuade others of that view. Rather, the main purpose of the original tweet was to mock those who disagree, and after some of those disagree-ers chimed in, the user posted follow-up tweets such as "the reason java has type erasure is that Wadler et al know what they are doing, unlike users of java". Unfortunately, this makes it hard to find out what (s)he's actually thinking; but fortunately, it also likely means that it's not very important to do so. People with actual depth to their views don't generally resort to trolls that are quite this content-free.
One good thing is that there was no need to change JVM when generics were introduced. Java implements generics at compiler level only.
avoids c++-like code bloat because the same code is used for multiple types; however, type erasure requires virtual dispatch whereas the c++-code-bloat approach can do non-virtually dispatched generics