2009-02-18 12 views
7

A menudo he pensado que sería una buena idea permitir el uso de matrices como objetos propios con sus propios métodos en lugar de depender de clases auxiliares como Arrays, Arrays y ArrayUtils.¿Debería Java tratar arreglos como objetos?

Por ejemplo:

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

estoy seguro que no soy el primero con esta idea, pero he tenido problemas para la búsqueda de otros que han escrito sobre esto antes. ¿Alguien puede ayudarme con algunas referencias sobre este tema?

¿Se piensa que esta es una buena o mala idea, y por qué?

¿Qué tan fácil sería implementarlo?

Algunos otros ejemplos podrían incluir (pero no se colgó en ellos, son ajenos a la pregunta en sí misma):

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); 
+0

¡Una gran pregunta! :) –

+0

No estoy seguro de si estás tomando el mickey, Bill :-) Es una pregunta sobre el reenvío de alguien ya que lo habría escrito, con suerte para educarlos.Por eso lo busqué en la wiki, no representaba prostitución para mí. – paxdiablo

+0

Estaba siguiendo los otros hilos. No pude resistir la tentación de divertirme un poco. Ahora que realmente lo pienso, es una pregunta decente. –

Respuesta

7

matrices no son clases de Java para una buena razón - se asignan bien en la comprensión de las personas de cómo debería funcionar una matriz a partir de la experiencia con lenguajes tipo C. También existen razones de rendimiento para hacer arreglos de contenedores de bajo nivel en lugar de objetos. Debido a esto, a veces hay beneficios de rendimiento al usar una matriz primitiva en lugar de una Colección.

Si desea utilizar objetos, debe utilizar una Colección (una ArrayList es un ejemplo de una colección). Puede ser torpe, pero las Colecciones proporcionan el tipo de buen acceso metodológico que parece desear.

+1

Estoy de acuerdo en que el tratamiento de arreglos como primitivos tiene sentido en el '95, sin embargo, creo que es hora de un enfoque más orientado a objetos. Al igual que el auto-boxing/un-boxing, esto trata las funciones ya disponibles para las matrices con un archivo adjunto más cercano. –

+2

Las matrices no son primitivas. Lea los documentos para Class.isPrimitive. –

+0

'Orientación a objetos' no siempre es algo bueno Peter! –

1

No es una idea BAD. Lo que pasa es que ya se ha hecho en Colecciones. Intenta extender ArrayList si quieres volverte loco.

+0

Lo que ArrayList no tiene es un soporte eficiente para las primitivas, el operador [] crea dos objetos (el ArrayList y el objeto []) cuando solo necesita uno. –

3

Sí. Pero soy de la opinión de que Java no debería tener ninguna primitiva en absoluto. Creo que los primitivos en Java son un descanso de la limpieza del lenguaje. Todo en Java debería ser objetos. Sea o no los objetos se asignan sobre la pila o el montón debe haber una aplicación detalle de la JVM no una construcción del lenguaje. Pero creo que mi opinión podría ser más radical que la mayoría.

Antes del autoboxing, el tratamiento de primitivas y objetos era muy engorroso.

Si matrices eran objetos y podrían ser autoboxed (y generisized!), Podríamos tener algo como

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

o

Array<Class<? extends MyBaseObject>> myArray = {ExtendedObject.class} 
ExtendedObject object = myArray[0].newInstance(); 
.... 
+0

Estoy de acuerdo en que las primitivas que no pueden tratarse transparentemente como objetos son desafortunadas. El compilador/JVM debería poder resolverlo. ArrayUtils tiene dos métodos toObject() y toPrimitive(). Podría tener otro método para cambiar el tipo de la matriz. –

+0

Sugeriría que Array y Entero [] son ​​dos formas de escribir lo mismo. ;) –

+0

Es demasiado tarde para arreglar cosas como estas en Java. Eche un vistazo a los idiomas en los que han formado parte del diseño desde el principio. Por ejemplo, en Scala todo es un objeto. –

5

Esos métodos empiezan a buscar un montón, como el rubí o el pitón modismos. Desafortunadamente no puedes hacer eso en Java (ojalá pudieras).

Por un lado, como han señalado otros, las clases de colecciones lo hacen por usted. Por otro lado, myarray.sort() no es tan agradable porque puede crear matrices de objetos para los cuales no se ha definido la ordenación. Supongamos que tengo

Foo[] foos; 

Y Foo no es Comparable. ¿Qué sucede en foos.sort()?Definitivamente no quieren tener que trabajar sólo para las primitivas

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

y ciertamente no podría tener el compilador sólo permite la sintaxis de objetos comparables. Y una vez que llegue a algo así como

myarray.add(new Foo()); 

es una especie de sentido, ya que las matrices de Java no son growable.

Se habría bueno si imprimir una matriz no le dio inútil que

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

basura, sin embargo.

+0

ArrayUtils.add(), addAll() y remove() devuelve una nueva matriz con el elemento agregado. –

+0

Estos métodos son muy útiles para administrar una matriz cuando no quiere sobrecargar una ArrayList. –

0

Para aquellos que se perdieron una publicación anterior que se cerró. Algunos otros ejemplos incluyen

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(); 
+0

Copiaré esto a la pregunta como un apéndice, Peter. – paxdiablo

2

Antes de responder a debe, yo le dirá el estado de este problema.

En Java, las matrices se consideran objetos; puede almacenarlos en una lista, por ejemplo. Sin embargo, son objetos especiales porque heredan de Object pero no se crean instancias ni se accede a ellos con la misma sintaxis (gracias por la corrección de Peter). La JVM los optimiza agresivamente para problemas obvios de rendimiento y, por lo tanto, la forma en que se almacena una matriz depende de la implementación.

Por lo tanto, el argumento de Sun sería que, si otorgaran una API de objeto para la matriz, podría requerir cierto hardware, software u otras características de especificación.

La única interfaz real para matrices es el método estático System.arrayCopy o los métodos estáticos Array. *, Que se copiarán de forma más eficiente a/desde matrices.

En respuesta a SHOULD; se ha resuelto, aunque un estándar sería mejor que la respuesta: use ArrayList.

+0

Las matrices implementan solo el método clone(), todos los demás métodos se heredan de Object. No es que no estén implementados/disponibles. Son. Todos ellos. –

2

Sí, creo que las matrices deberían tener una API definida más allá de la especificada en el idioma. En particular, es molesto que Foo[] no implemente Iterable<Foo>. Sí, sé que es fácil envolverlo, pero es molesto que tengas que hacerlo.

.NET obtiene esto principalmente correcto, con el tipo Array que es principalmente para acceso no genérico, y varias interfaces genéricas que se consideran implementadas por las matrices reales. Por ejemplo:

IList<int> intList = new int[10]; 

(que ayuda a que los genéricos de .NET hacer frente a los tipos primitivos de Java mejor que lo hace.)

Las únicas desventajas que he visto de este enfoque es que las matrices pueden ser covariantes en .NET , pero los genéricos normales no lo son, y las cosas se vuelven un poco confusas con las matrices basadas en cero y las matrices rectangulares.

Como nota aparte, varias personas se han referido a las matrices como primitivas en este hilo. Si bien ciertamente tienen un manejo especial, no están definidos como primitivos. Desde el language spec, section 4.2:

Un tipo primitivo está predefinido por el lenguaje de programación Java y nombrada por su palabra clave reservada (§ 3.9):

 
PrimitiveType: 
     NumericType 
     boolean 

NumericType: 
     IntegralType 
     FloatingPointType 

IntegralType: one of 
     byte short int long char 

FloatingPointType: one of 
     float double 
1

Creo que esto es muy difícil de poner en práctica sin romper la compatibilidad en muchos niveles.

  • JVM trata las matrices de forma diferente a otros objetos. La creación/inicialización es diferente: no se llama a ningún constructor por una cosa. ¿Cómo le gustaría agregar nuevos métodos? Si al agregar una superclase, ¿llamarías a su constructor?
  • Las matrices saben el tipo de elemento en tiempo de ejecución, los genéricos no. Si quisiera agregar una nueva superclase para todas las matrices (como sugirió en la pregunta original), ¿la haría genérica? También tenga en cuenta que las matrices son covariantes en Java, los genéricos no lo son.
  • Las matrices tienen un conjunto fijo de métodos/campos especificados en la Especificación del lenguaje Java (todos los métodos de Objetos, que se nombran explícitamente en JLS, campo de longitud). Agregar nuevos miembros es probable que rompa clientes existentes dependiendo de esto. (Es decir, las matrices no son de su clase al azar)
  • serialización matriz probablemente se vería afectado demasiado
  • Estoy seguro de que hay más detalles de implementación que harían de esta extremadamente duro :-(
  • programas compilados para trabajar con nuevos métodos haría no funcionan en las JVM mayores. Lo que es peor, dependiendo de la aplicación, los programas compilados para el viejo JVM no pueden trabajar con matrices modificadas en nuevas máquinas virtuales de Java.

me gustaría tener métodos directamente en "clase array", I don' Creo que es posible implementarlo ahora.

1

Personalmente me gusta la idea de que todo sea un objeto, y esto ya se ha hecho en smalltalk, por ejemplo. Sin embargo, las consecuencias de hacer que todo, incluso los métodos/funciones, sean un objeto son de gran alcance (eche un vistazo a smalltalk para ver a qué me refiero). Siendo consistente en la aplicación del "todo es un objeto", la regla resulta en un lenguaje que ya no se parece en nada a C (o Java).

Java fue diseñado muy conscientemente para ser accesible a los programadores C, y ha tenido éxito en eso, pero en realidad no está muy orientado a objetos en comparación con smalltalk. Es patrimonio como una variante C aparece en todo el lugar, como en matrices y el hecho de que hay primitivos.

Para responder a la pregunta de DEBERÍA, diría que no, porque Java ya no sería Java con ese cambio. Como han señalado otros, hay otras clases que le permiten manejar tareas que podrían haberse realizado con una matriz en C que utiliza objetos en Java, pero eliminar todas las matrices y tipos de datos primitivos es una tarea que queda mejor para un idioma diferente , EN MI HUMILDE OPINIÓN.

0

Una razón creo que no sería tan difícil es que se puede añadir métodos indirectamente mediante la modificación de objetos (un corte real de acuerdo, pero se nota que funciona) Añadiendo métodos de objeto, el siguiente código

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); 

imprime

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

esto funciona con Java 5 & 6 y tanto el compilador e IDE manejan esto como yo esperaba.

Cuestiones relacionadas