Suggestions for Java Generics Semantics in Java Version 7.0 - W/O Attachments

Jaisimha Narahari jcnarahari at yahoo.com
Wed Jun 10 23:44:41 PDT 2009


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<Integer> 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<Object> lo = new ArrayList<Integer>;


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


                                 In Java
5.0 Generics, List<Object> and List<Integer> 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<E> [], List<String> [], E[], etc 
   also get forbidden,
on account of the fact that Arrays are "Reified" 
   types,   implying that they carry over their full type
info into the 
   Runtime, and are therefore aware of the type  of their contained 
   elements at runtime, in
direct contrast to Generic Types, which,   
   because of Erasure,  discard the knowledge of the type of their   contained elements (i.e., Type Parameters) and are therefore   
  "non-reifiable" types. 
 

[However, the expression E[] can be used, (without “new” used for its
creation), to specify an array of ANY REGULAR TYPE, not Generic Type. 
This syntax therefore is not really one to be associated with Generic Types].

Having introduced Generic Types for the very purpose of Type
System Robustness, in the interest of Backward Compatiblity with Raw Types of
previous Java versions, Java 5.0 is promptly losing that very advantage
provided by Generic Types, for which they were introduced in the first place.

To be fair, Java 5.0 also provides a "patch up"
API in the classes provided by java.util.Collections.checkedXXX classes, which
try to reverse the effects of Erasure by carrying over the type info of Type
Parameters of Generic Types also into the runtime, by separately providing
reflection ".class" types of the Type Parameters as part of the
checkedXXX classes.

While this provision re-ensures type safety w.r.t. its loss
due to erasure, there is no compensation concerning the above two
"makeshift" rules that end up greatly restricting Java from having a
very robust, elegant Type System, wherein Parameterized Types could enjoy the
same status as any other type, without getting quirks and twists in their usage
imposed upon them.

The evolution of a programming language should not forever
be constrained by the sins of its past versions, which in this case translates
to the existence of Raw Types, and consequent necessity to inter-operate with
Legacy Code making use of these Raw Types.

Therefore, in the interest of Type System Robustness (which
seems to me to be of higher priority in the longer term, in comparison to any
immediate need for Backward Compatibility which constricts the language from
breaking the "mold" to make true progress), I would like to  put forward these suggestions:

From Java Version 7.0, going forward:

                  (1) "Deprecate" Raw Types 

                  (2) Remove Backward
Compatibility provision and therefore convert 


                       "Erasure" to
"Reification"  for Generic Types, the
consequence of which 


                         will render the above two rules for the usage of Generic Types 
                        unnecessary,
making all types provided by the language behave 


                        uniformly, most especially  without violating OOP
principles in what is 
                        essentially an OOP Language.

 

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.



      


More information about the jdk7-dev mailing list