tags:

views:

686

answers:

10

I have often thought it would be a good idea to allow the use of arrays as proper objects with their own methods instead of relying on helper classes like Arrays, Arrays and ArrayUtils.

For example:

ints.sort();                 // Arrays.sort(ints);
int[] onemore = ints.add(8); // int[] onemore = ArrayUtils.add(ints, 8);

I am sure I am not the first with this idea but I have had trouble searching for others who have written about this before. Can anyone help me with some references on this topic?

Is this thought to be a good or bad idea, and why?

How easy would this be to implement?

Some other examples might include (but don't get hung up on them, they're extraneous to the question itself):

int[] ints = {5,4,3,2,1};

// Arrays.sort (ints);
ints.sort();

// int pos = Arrays.asList(ints).indexOf (5);
// int pos = ArraysUtils.indexOf (ints, 5);
int pos = ints.indexOf (5);

// Arrays.reverse (ints);
ints.reverse();

Array<Integer> array = ints; // cast to super class.

// int length = Array.getLength (array);
int length = array.getLength();

// Object n = Array.get (array, 3);
Object n = array.get (3);

// Array.set (array, 3, 7);
array.set (3, 7);

Object obj = array;
// if (obj instanceof int[])
//     System.out.println(Array.toString((int[]) obj));
// else if (....)
System.out.println (obj);
+8  A: 

Arrays are not classes in Java for a good reason - they map well onto people's understanding of how an array should work from experience with C-style languages. There are also performance reasons for making arrays low-level containers rather than objects. Because of this, sometimes there are performance benefits to using a primitive array rather than a Collection.

If you want to use objects, you should just use a Collection (an ArrayList is an example of a collection). It can be clunky, but Collections provide the type of nice methodological access that you seem to want.

James Thompson
I agree that treating arrays like primitive made sense in '95, however I think it is time for a more object-orientated approach. Like auto-boxing/un-boxing this treats the functions already available to arrays with closer attachment.
Peter Lawrey
Arrays aren't primitives. Read the docs for Class.isPrimitive.
Jon Skeet
'Object-orientation' isn't always a good thing Peter!
PintSizedCat
Vector is a legacy class don't use. use ArrayList instead
Andreas Petersson
Vector isn't a legacy class, it's the thread-safe version of ArrayList nowadays.
Esko
lol at the 'Vector' example...
Richie_W
+1  A: 

It is not a BAD idea. Thing is it has already been done on Collections. Try extending ArrayList if you wanna go crazy.

omgzor
What ArrayList lacks is efficient support for primitives, the [] operator, creates two objects (the ArrayList and the Object[]) when you only need one.
Peter Lawrey
+3  A: 

Yes. But I'm of the opinion that Java should not have any primitives at all. I think primitives in Java are a break from the cleanness of the language. Everything in Java should be objects. Whether or not the objects are allocated on the stack or the heap should be an implementation detail of the JVM not a language construct. But I think my opinion might be more radical than most.

Before autoboxing, dealing with primitives and objects was very cumbersome.

If arrays were objects and could be autoboxed (and generisized!), we could have something like

Array<Integer> myArray = new Integer[];
myArray.add(8);
int x = myArray[0];
....

or

Array<Class<? extends MyBaseObject>> myArray = {ExtendedObject.class}
ExtendedObject object = myArray[0].newInstance();
....
Laplie
I agree that primitives which cannot be transparently treated as objects is unfortunate. The compiler/JVM should be able to work it out.ArrayUtils has two methods toObject() and toPrimitive(). It could have another method to change the type of the array.
Peter Lawrey
I would suggest that Array<Integer> and Integer[] be two ways of writing the same thing. ;)
Peter Lawrey
It's too late to fix things like these in Java. Have a look at languages in which they have been part of the design since the beginning. For example in Scala everything is an object.
Esko Luontola
+5  A: 

Those methods start to look an awful lot like ruby or python idioms. Unfortunately you don't get to do that in java (wish you could).

For one, as others have pointed out, the collections classes do it for you. For another, myarray.sort() isn't so nice because you can create arrays of objects for which sorting has not been defined. Suppose I have

 Foo[] foos;

And Foo is not Comparable. What happens on foos.sort()? We definitely wouldn't want to have it only work for primitives

int[] ints; 
ints.sort(); //legal
Object[] objects;
objects.sort(); //illegal

and you certainly couldn't have the compiler only allow the syntax for comparable objects. And once you get to something like

 myarray.add(new Foo());

it's sort of pointless, as arrays in java aren't growable.

It would be nice if printing out an array didn't give you that useless

([I'm an array(*&(*

rubbish, though.

Steve B.
ArrayUtils.add(), addAll() and remove() returns a new array with the element added.
Peter Lawrey
These methods are very useful for managing an array when you don't want to overhead of an ArrayList.
Peter Lawrey
A: 

For those who missed a previous post which was closed. Some other examples include

int[] ints = {5,4,3,2,1};
ints.sort(); // instead of Arrays.sort(ints);
int pos = ints.indexOf(5); // instead of Arrays.asList(ints).indexOf(5); or ArraysUtils.indexOf(ints, 5);
ints.reverse(); // instead of Arrays.reverse(ints);
Array<Integer> array = ints; // cast to super class.
int length = array.getLength(); // instead of Array.getLength(array);
Object n = array.get(3); // instead of Array.get(array, 3);
array.set(3, 7); // instead of Array.set(array, 3, 7);
Object obj = array;
System.out.println(obj); // prints [5,4,7,2,1] instead of having to
// if (obj instanceof int[]) System.out.println(Array.toString((int[]) obj)); else if (....)

int[] ints2 = ints.copyOf(2);
int[] ints3 = ints.subArray(2,4);
ints.sort(myComparator);
List<Integer> list = ints.asList();
Set<Integer> set = ints.asSet();
long total = ints.sum();
double avg = int.average();
int max = ints.max();
int max2 = ints.max(myComparator);
http://commons.apache.org/lang/api/org/apache/commons/lang/ArrayUtils.html
int[] onemore = ints.add(8); // instead of ArrayUtils.add(ints, 8);
int[] moreInts = ints.addAll(ints2); // instead of ArraysUtils.addAll(ints, ints2);
int[] oneless = int.remove(3); // instead of ArrayUtils.remove(ints, 3);
Integer[] integers = int.toObject();
int[] intsAgain = integers.toPrimitive();
Peter Lawrey
I'll copy this to the question as an addendum, Peter.
paxdiablo
+2  A: 

Before I answer for SHOULD, I will tell you the state of this issue.

In Java, arrays are considered objects -- you can store them in a List for example. However they are special objects in that they inherit from Object but are not instantiated or accessed with the same syntax (thanks for the correction Peter). They are aggressively optimized by the JVM for obvious performance issues, and thus the way an array is stored is dependent on implementation.

So the Sun argument would be that, if they gave an object API for the array, it could require certain hardware, software, or other specification features to be in place.

The only real interface for arrays are the System.arrayCopy static method or the Array.* static methods, which will most efficiently copy to/from arrays.

In response to SHOULD; it has been solved, although a standard would be better than the answer: use ArrayList.

Overflown
Arrays implement only clone() method, all other methods are inherited from Object. It not that they are not implemented/available. They are. All of them.
Peter Štibraný
+2  A: 
Jon Skeet
+1  A: 

I believe this is very hard to implement without breaking compatibility at many levels.

  • JVM treats arrays little differently than other objects. Creation/initialization is different: no constructor is called for one thing. How would you want to add new methods? If by adding superclass, would you call its constructor?
  • Arrays know type of element in runtime, generics don't. If you wanted to add new superclass for all arrays (like you suggested in original question), would you make it generic? Also keep in mind that arrays are covariant in Java, generics aren't.
  • Arrays have fixed set of methods/fields specified in Java Language Specification (all methods from Objects, which are explicitely named in JLS, length field). Adding new members is likely to break existing clients depending on this. (i.e. arrays are not your random class)
  • Array serialization would probably be affected too
  • I am sure there are more implementation details which would make this extremly hard :-(
  • Programs compiled to work with new methods would not work on older JVMs. What's worse, depending on implementation, programs compiled for old JVMs may not work with modified arrays on new JVMs.

I would like to have methods directly in "Array class", I don't think it's possible to implement it now.

Peter Štibraný
+1  A: 

I personally like the idea of everything being an object, and this has already been done in smalltalk, for instance. However, the consequences of making everything, even methods/funcitons an object are very far-reaching (have a look at smalltalk to see what I mean). Being consistent in the application of the "everything is an object"-rule results in a language that doesn't look anything like C (or Java) anymore.

Java was very consciously designed to be approachable to C programmers, and it has succeeded at that, but it's not actually very object oriented compared to smalltalk. It's heritage as a C variant shows up all over the place, like in arrays and the fact that there are primitives.

So to answer the question of SHOULD, I would say no, because Java wouldn't be Java anymore with that change. As others have pointed out, there are other classes that let you handle tasks which might have been done with an array in C using objects in Java, but to get rid of primitive data types and arrays alltogether is a task better left to a different language, IMHO.

Galghamon
A: 

One reason I believe it would be not so hard is that you can add methods indirectly by modifying Object (A real hack I agree, but it shows it works) By adding methods to Object, the following code

int[] ints = {5, 4, 3, 2, 1};
System.out.println("ints= "+ints);
ints.sort();
System.out.println("after sort() ints= "+ints);
ints = ints.add(6);
System.out.println("after add(6) ints= "+ints);

Prints

ints= [5, 4, 3, 2, 1]
after sort() ints= [1, 2, 3, 4, 5]
after add(6) ints= [1, 2, 3, 4, 5, 6]

This works with Java 5 & 6 and both the compiler and IDE handled this as I expected.

Peter Lawrey