Suggestions for Java Generics Semantics in Java Version 7.0 (original) (raw)

Maurizio Cimadamore Maurizio.Cimadamore at Sun.COM
Thu Jun 11 03:06:37 PDT 2009


Hi Jaisimha, see my comments below:

Jaisimha Narahari wrote:

I found that my previous post showed up without the attachment I'd sent, so I am posting again w/o the attachment, having transferred its contents directly into this post.

It is a bit of a read, and contains also some explanations that systems guys working on JDK 7 do not really need. Because it comes from an applications developer in Bangalore (I am not a systems guy). I hope you all will patiently read it. Here goes: I sincerely feel that the OO paradigm has suffered a setback with Backward Compatibility support in Java 5.0, for Raw Types in java.util.Collections of Previous Java Versions. Especially the sacrifices made w.r.t the semantics of Generics in Java 5.0 to accommodate this interoperability with Legacy Code of previous Java versions. So I am making suggestions for correcting the situation with Java 7.0. I have included the arguments in favor of my suggestions. I definitely hope that these will be looked into, and even implemented, if there is no flaw in my arguments, and if bigger constraints do not forbid them from being incorporated into Java 7.0. Here's hoping.. :

Suggestions for Java Generics Semantics in Java Version 7.0 It seems to me that in the interest of Backward Compatibility with Raw Types of java.util.Collections in versions previous to Java 5.0, the robustness of Generic Types introduced in Java 5.0 has been sacrificed. In order to make Generic Types of Java 5.0 inter-operable with Raw Types of java.util.Collections in versions previous to Java 5.0, "Erasure" has been resorted to. Erasure basically refers to the discarding of the type info of Type Parameters of Generic Types at runtime, so that a Generic Type at run time is identified only by its Base Type. This means, for example, that a variable declared as of type List at compile time is considered merely as a variable of type “List”, in order that it can be assigned/ passed as argument to another variable in Legacy Code which is also of type” List” (A Raw Type). Raw Types, since they discard all type checking on the type of their contained elements, contribute to total loss of Type Safety in Java, which is the very reason that java.util.Collections classes in Java 5.0 were made Generic. The issue here is whether interoperability with legacy code is a sufficient enough justification to sacrifice Type Safety, given that this provision has also resulted in the following two contrived rules in the operation of Generic Types in Java 5.0: (1) For the sake of determining Type Hierarchy of Generic Types, the Type Parameters are not to be considered. That is, code such as the line below is rejected by the compiler: List lo = new ArrayList; Actually this subtyping rule is a standard sound subtyping rule between generic types. You might wonder why it is possible e.g. to assign an Integer[] to an Object[] - since that assignment is not type-safe. On the other hand, the JVM has a way to dynamically check the correctness of assignments involving array so that type-safety is always enforced at runtime.

On the other hand, because of erasure, given that there's no runtime support for generics, there's no way to write a 'generic' version of the arraystore check. Which means that the code above should be rejected as unsafe: consider the following program:

List li = new ArrayList();

List lo = li; lo.add("Hello!"); //ok - adding a String to a List Integer i = li.get(0); //ClassCastException - cannot convert String to Integer

even as pure OOPS principles allow an Integer to be recognized as an Object.

In Java 5.0 Generics, List and List are treated as totally unrelated types by the above rule, not only violating the purity of OOPS but also sacrificing type system robustness.

(2) As a direct consequence of the above rule, any kind of Array Creation involving Generic Types, such as List [], List [], E[], etc also get forbidden,

See above - because of type-erasure there's no way fo rthe JVM to take into account type-parameters info when performing the arraystore routine

List l = new ArrayList(); Object o = (ArrayList)l; //would pass with JDK5/6, would fail with reification

This is a serious source and behavioral incompatibility that might affect a lot of users. This is just an example of the subtle problems that might arise when reification support is added to the language.

But it's not just about plain generics - among the other problems: what is the runtime semantics of more exotic types, like e.g. intersection types? Should reification support wildcards? If so, should the JVM runtime system implement the full subtyping algorithm described by the JLS? How is this going to affect decidability?

Legacy code can still make use of JDK up to Java version 6.0 for inter-operability, with support removed from Java 7.0.

An important point to note in this regard is that Java will continue to violate OO principles (at least according to OO purists) by having a single root super class called "Object" for all of its types, both related types and unrelated types. This has in fact been responsible for type mismatches in code leading to both compile time and runtime errors such as ClassCastException, ArrayStoreException, etc. This provision introduced from Java's inception is ARGUABLY a REQUIRED VIOLATION of OO in the interests of pragmatism, and has served its purpose well, just as similar violations of OO Principles in the implementation of "Enums" in Java 5.0 are (maybe) REQUIRED for similar pragmatic reasons. It will rock the foundations of Java's API to try and have separate class hierarchies for unrelated types, and so the single super class "Object" for all types will have to remain. Enums and their implementation have only furthered the interests of Type Safety. Violations of OO in the internal implementation of Enums is based upon straitjacket constraints that must be applied to what can be allowed in the developer's domain, with the system enforcing a good portion of the behavior of Enums to make them work. Allowing full OO programming freedom with Enums to developers would have implied unworkable language semantics. Therefore the nearest thing to "ideal" OO that Java can now achieve in practice, is with the implementation of the above two suggestions in Java 7.0. Java must only then continue to evolve from there. Thanks for your patience.

Thanks Maurizio



More information about the jdk7-dev mailing list