JDK-4654312 : (array) Retrofit arrays to become fully-fledged Collections
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 1.3.1
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2002-03-18
  • Updated: 2021-03-03
  • Resolved: 2016-04-21
Related Reports
Relates :  
Description

Name: nt126004			Date: 03/18/2002


FULL PRODUCT VERSION :
java 1.3.1-b24

FULL OPERATING SYSTEM VERSION :
N/A

A DESCRIPTION OF THE PROBLEM :
This language change seems an obvious idea with very
significant benefits - not least a simplification of the
language (most language changes produce a complication). It
may also be possible without changing the JVM. However I've
never come across the idea so maybe there is a big
technical problem somewhere.

When we have generic types (JSR-14), arrays of reference
types could be made to implement the List interface, which
would allow them to be passed to functions which expect a
List or Collection. Currently there are many APIs which
take arrays (for speed) and Lists/Vectors (for
flexibility), and lots of code has to awkwardly convert
between the two representations. Basically after JSR-14,
Java will have **two** systems of parameterized types (the
original one being arrays), and **two** systems of
collections (arrays being the original ones). This proposal
could hopefully merge the two without breaking existing
code.

In a nutshell, arrays of reference types (not primitive
types) could, at the language level, pretend to be
specializations of a new generic class Array<T> derived
from List. This class could reveal all of the existing
magic behaviour of arrays (their derivation from Object,
that strange 'length' field, their Cloneability and
Serializability, etc.) like any other API. Something like
this:

public final class java.util.Array<T> extends
AbstractList<T> implements Cloneable, Serializable,
RandomAccess {
		public final int		length;
		// same as size()
		public			Array<T>(int size);
		// same as new T[size]
		public			Array<T>(Collection<T>);	// might be useful; simpler than Collection.toArray(T[])

		public Object		clone();
		public boolean		contains(Object o);
		// from Collection interface
		public T		get(int index);
		// from List interface; same as this[index]
		public Iterator<T>	iterator();
		// from Collection interface
		public int		size();
		// from Collection interface; same as this.length
		// etc. etc. (various other methods from
the Collection/List interfaces)
}

All arrays of reference types (not primitive types) would
appear to be instances of this class. Array operations
using the [] syntax could be regarded as 'syntactic sugar'
for normal method and constructor calls. E.g.
String[] names = new String[10];
names[0] = "Fred";
String x = names[0];

would be equivalent to:
Array<String> names = new Array<String>(10);
names.set(0,"Fred");
String x = names.get(0);

Of course, everybody would normally use the [] syntax, but
the bonus is that you could pass a normal array to a method
which expected a List, without either writing a separate
method or converting to/from a List. For code using arrays
or Arrays directly (as opposed to via the List interface),
the compiler would produce the same bytecode as before
(i.e. using the various array bytecodes).
	
The Array<T> class would implement the other useful methods
of List such as indexOf(Object), iterator() etc. List
specifies several optional operations which Array would not
implement because arrays aren?t resizable: add, addAll,
clear, remove, removeAll, retainAll. So these would all
throw the UnsupportedOperationException.

A separate but closely-related proposal would be to make it
easy for existing array code to be rewritten to take Lists
instead. This could be done by a form of simple operator
overloading, whereby List code could use the [] syntax as
an alternative to calling get and set. Instead of adding
new operator[] methods to List (which would be changing an
existing interface), the compiler could just translate []
into a get or set method call, so you could use the []
syntax with any class which has set/get methods, not just
Lists. In effect, get() and set() would be the official
operator overloading method names for [], equivalent to
C++'s operator[] (). For instance:
	LinkedList<Cat> cats = new LinkedList();
	cats.add(new Cat("Fred"));
	Cat myCat = cats[0];	// calls LinkedList.get
	cat[0] = new Cat("Jim");	// calls
LinkedList.set

As well as providing this very useful syntax, existing
array code could be generalized to use Lists instead, with
only a few minor changes (e.g. the use of the length
variable, System.arraycopy() etc.).

The biggest problem I can see with Array<T> this is that
the rules for generics are more restrictive than for arrays:
Cat[] cats = new Cat[10];
Animal[] animals = cats;		// legal

List<Cat> cats = new List<Cat>(10);
List<Animal> animals = cats;		// illegal
according to JSR-14

But maybe this isn?t a problem and the Array class can
allow this special behaviour?
Array<Cat> cats = new Array<Cat>(10);
Array<Animal> animals = cats;	// make this case legal?

I don't really know the implications of this. Here are some
other issues. Multidimensional arrays: maybe these will
just work, i.e. String[][] is the same as
Array<Array<String>>. Reflection on Arrays: this would have
to give the same results as for existing arrays ? maybe
this is a problem.

For what it's worth, this change could precipitate a tidy-
up of the existing Arrays class, whose static methods for
sorting, searching etc. would be no longer be needed, as
they are already implemented by the Collections class as
operations on Lists. Or we could add non-static methods for
sort() etc. to class Array<T>. Oddities like
System.arraycopy could also be made non-static methods of
Array<T>.

(As for arrays of primitive types, these obviously could
not be specializations of Array<T>. They could be left
untouched, or possibly pretend to be instances of a new set
of classes FloatArray, IntArray etc. The benefits of this
are less clear, other than generally tidying everything
into the class hierarchy. I suppose these classes could
have a base class PrimitiveArray with useful functions for
sorting etc. to avoid the kind of static functions we find
in the Arrays class.)


This bug can be reproduced always.
(Review ID: 139266) 
======================================================================

Comments
There are a number of long-standing issues mentioned here. This isn't a simple RFE, but instead it requires a comprehensive effort across the JVM, the language, and the libraries. Some parts of this, and related topics, may be covered by Project Valhalla: http://openjdk.java.net/projects/valhalla/ Closing this bug as Won't Fix.
21-04-2016

EVALUATION This is clearly a desirable goal, but the devil is in the details. The resulting array classes would have incompatible equals(Object) behavior. Also the covariant subtyping of arrays does not match the treatment of parameterized Lists. These problems may not be insurmountable, but they do present serious obstacles. ###@###.### 2002-04-14
14-04-2002