length - ¿Por qué los métodos de la "clase Arrays" son estáticos en Java?
java array of objects (8)
Buena observación. Observe también que no todas las matrices pueden clasificarse. Solo se pueden ordenar las matrices de primitivas y Objetos que implementan la interfaz Comparable
. Por lo tanto, no es posible un método de sort()
general sort()
que se aplique a todas las matrices. Y entonces tenemos varios métodos estáticos sobrecargados para cada uno de los tipos admitidos que son realmente ordenables.
Actualizar:
@Holger señala correctamente en los comentarios a continuación que uno de los métodos estáticos sobrecargados es Arrays.sort(Object[])
pero los documentos indican explícitamente:
Todos los elementos en la matriz deben implementar la interfaz
Comparable
.
Por lo tanto, no funciona para los Objetos que no implementan Comparable
o una de sus subinterfaces.
Estaba revisando la documentación de Java y aprendí que los métodos en la clase Arrays
en Java son estáticos. Realmente no entiendo la razón detrás de por qué lo hicieron estático.
Por ejemplo, el siguiente código viola el enfoque OO, porque si tengo un tipo, ''X'', entonces todos los métodos que actúen en él deberían estar dentro de él:
int[] a = {34, 23, 12};
Arrays.sort(a);
Sería mejor si hubieran implementado de la siguiente manera:
int[] a = {34, 23, 12};
a.sort();
¿Alguien puede explicarme un poco sobre esto?
En Java no hay forma de ampliar funcionalmente una matriz. Todas las matrices heredan de Object
pero esto da muy poco. En mi humilde opinión, esta es una deficiencia de Java.
En cambio, para agregar funcionalidad a las matrices, los métodos de utilidad estáticos se agregan a clases como Array
y Arrays
. Estos métodos son static
ya que no son métodos de instancia.
En primer lugar, Arrays
es una clase de utilidad, que hace exactamente eso: expone métodos estáticos. Está separado de cualquier instancia arr[]
y no tiene ninguna relación OO con él. Hay varias clases como esa, como Collections
o varias StringUtils
.
Las matrices son colecciones, se usan para almacenar datos. Arrays.sort()
es un algoritmo que ordena la colección. Puede haber muchos otros algoritmos que clasifiquen datos de manera diferente, todos ellos se usarían de la misma manera: MyAlgorithm.doSthWithArray(array)
. Incluso si hubiera un método de sort()
en una matriz (tendría que ser una SortableArray
, porque no todos los objetos pueden clasificarse automáticamente), todos los demás algoritmos deberían llamarse de todos modos. A menos que se haya introducido un patrón de visitante ... Pero eso hace que las cosas sean demasiado complicadas, por lo tanto, no tiene sentido.
Para una colección de Java hay Collections.sort()
, incluso en C ++ hay std::sort
que funciona de manera similar, como lo hace qsort
en C. No veo un problema aquí, veo coherencia.
La clase Arrays
contiene métodos que son independientes del estado, por lo tanto, deben ser static
. Es esencialmente una clase de utilidad.
Si bien los principios de OOP no se aplican, la forma actual es más clara, concisa y más legible, ya que no tiene que preocuparse por el polimorfismo y la herencia. Todo esto reduce el alcance, lo que en última instancia reduce las posibilidades de que se arruine algo .
Ahora, usted puede preguntarse "¿Por qué no puedo extender la funcionalidad de una matriz en Java?". Una buena respuesta es que esto introduce potenciales agujeros de seguridad , que podrían romper el código del sistema.
Las matrices son como genéricos de segunda clase. Cuando haces una matriz, crea una clase personalizada para el tipo de matriz, pero no tiene todas las funciones porque decidieron cómo funcionarían las matrices antes de que realmente desarrollaran el lenguaje.
Eso, combinado con el mantenimiento de la compatibilidad con versiones anteriores, significa que las matrices están atrapadas con una interfaz arcaica.
Es solo una parte antigua de la API.
Los métodos estáticos a veces se usan con fines de utilidad. Así que Arrays es una clase de utilidad para operaciones de matriz de propósito general. Del mismo modo, Collections es también una clase Util en la que se proporcionan métodos de utilidad.
Para mí esta es la solución perfecta. Tengo una matriz, y tengo una clase, Arrays, que opera sobre los datos en la matriz. Por ejemplo, es posible que desee mantener algunos números aleatorios y nunca querrá ordenar o cualquier otro método de utilidad; recibirá un comportamiento que no desea. Es por eso que en el diseño del código, es bueno separar los datos del comportamiento.
Puedes leer sobre el principio de responsabilidad individual .
Una matriz no es un objeto que almacena estado, más allá de los valores reales de la matriz. En otras palabras, es solo un "contenedor tonto". No "conoce" ningún comportamiento.
Una clase de utilidad es una clase que tiene solo métodos public static
que son funciones sin estado. La ordenación no tiene estado porque no hay nada que se recuerde entre llamadas a ese método. Se ejecuta "independiente", aplicando su fórmula a cualquier objeto que se pase, siempre que ese objeto sea "clasificable". Una segunda instancia de una clase Arrays
tendría un comportamiento diferente, así que solo tiene una instancia static
.
Como señaló Dariusz, existen diferentes formas de clasificar. Por lo tanto, podría tener MyArrays.betterSort(array)
así como Arrays.sort(array)
.
Si quisiera que la matriz "supiera" la mejor manera de ordenar sus propios miembros, tendría que tener su propia clase de matriz que extends
una matriz.
Pero, ¿qué pasaría si tuvieras una situación en la que quisieras una clasificación diferente en diferentes momentos en la misma matriz? Un ejemplo artificial, tal vez, pero hay muchos ejemplos similares del mundo real.
Y ahora te estás complicando. Tal vez una matriz de tipo T
ordena de forma diferente que el tipo S
....
Se simplifica con una utilidad estática y la interfaz Comparator<T>
.