Primitives in Generics

Gernot Neppert mcnepp02 at
Thu Jul 8 00:42:27 PDT 2010

Reinier, I think your proposal is propably off-topic with regards to
this mailing list, nevertheless I could not resist to respond ;-)

I like the idea of making efficient use of generic classes with
primitive type parameters possible. However, I'm worried that solely
relying on a JVM optimization will not be sufficient. Wouldn't it be
possible to gain efficiency on every VM if something along the
following could be adopted:

1. Let's assume the existence of a generic interface

L<T> {
   void add(T element);
   T get(int index);

2. The declaration of a variable of type L<p> where p is one of the 8
primitive types is possible.
If the compiler encounters such a variable, it assumes that L<p>
actually is equivalent to following 'extended' interface

   void add(P element);
   void add(p element);
   P get(int index);
   p get(int index);

where 'P' is the wrapper type corresponding to 'p'.

3. It would still remain illegal to declare an interface such as the
above 'by hand', since overriding by return type is illegal unless the
return types are covariant. However, the VM can cope with such
overrides; and the compiler will encounter no ambiguities, as
paragraph 4. will show.

4. With the assumptions made above, the following code would compile
to the most efficient bytecode, invoking the primitive versions of
'add' and 'get':

L<int> list;
int value = list.get(0);

5. There has to be a means of instantiating objects of type L<p>. With
the assumption made in 2., the solution is the same as with other
abstract classes:

A non-abstract class that implements L<p> for a primitive type p must
implement those methods from the synthetic L'<p> that use the
primitive type p, while the compiler will generate the necessary
bridge methods with the wrapper type P:

public class IntList implements L<int>
  public   void add(int element)
  // efficient int-based implementation

public   int get(int index)
   // efficient int-based implementation.


6. The types L<P> and L<p> will be assignment compatible in only one
direction: It will be possible to assign an instance of type L<int> to
L<Integer>, but not vice versa.

L<Integer> list1 = new IntList();  // OK
L<int> list2 = new ArrayList<Integer>(); // Will not compile

7. If the assignment from L<P>  to L<p> is forced through an unsafe
cast, the attempt to invoke a method of L<p> using the primitive type
p will result in a java.lang.NoSuchMethodException at runtime. This is
comparable to the ClassCastException that can be thrown arbitrarily
when unsafe casts are involved.

L<int> list = (List<int>)(List)new ArrayList<Integer>();
list.add(42); // Will throw NoSuchMethodException.

More information about the lambda-dev mailing list