2009-02-18 1 views
7

Ho spesso pensato che sarebbe una buona idea consentire l'uso di matrici come oggetti propri con i propri metodi invece di affidarsi a classi di helper come Array, Array e ArrayUtils.Java dovrebbe trattare gli array come oggetti?

Ad esempio:

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

Sono sicuro che io non sono il primo con questa idea, ma ho avuto problemi alla ricerca di altri che hanno scritto su questo prima. Qualcuno può aiutarmi con alcuni riferimenti su questo argomento?

Questo pensiero è una buona o cattiva idea e perché?

Quanto sarebbe facile da implementare?

Alcuni altri esempi potrebbero includere (ma non ottenere appeso su di loro, sono estranei alla domanda stessa):

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

Ottima domanda! :) –

+0

Non sono sicuro che tu stia prendendo il mickey lì, Bill :-) È un ripubblicare la domanda di qualcuno come avrei scritto, spero di educarli.Questo è il motivo per cui l'ho ideato io: nessun rep-whoring per me. – paxdiablo

+0

Stavo seguendo gli altri thread. Non potevo resistere alla tentazione di divertirmi un po '. Ora che ci penso davvero, è una domanda decente. –

risposta

7

array non sono classi in Java per una buona ragione - che mappa bene alla comprensione della gente di come un array dovrebbe funzionare dall'esperienza con i linguaggi in stile C. Ci sono anche ragioni di prestazioni per rendere gli array contenitori di basso livello piuttosto che oggetti. Per questo motivo, a volte ci sono vantaggi di prestazioni nell'utilizzo di una matrice primitiva piuttosto che di una raccolta.

Se si desidera utilizzare oggetti, è necessario utilizzare solo una raccolta (un ArrayList è un esempio di una raccolta). Può essere goffo, ma le raccolte forniscono il tipo di accesso metodologico che ti sembra opportuno.

+1

Concordo sul fatto che trattare gli array come primitivi avesse senso nel '95, tuttavia penso che sia tempo di un approccio più orientato agli oggetti. Come auto-box/un-boxing, questo tratta le funzioni già disponibili per gli array con un allegato più vicino. –

+2

Gli array non sono primitivi. Leggi i documenti per Class.isPrimitive. –

+0

"Orientamento all'oggetto" non è sempre una buona cosa Peter! –

1

Non è un'idea BAD. Il fatto è che è già stato fatto su Collections. Prova ad estendere ArrayList se vuoi impazzire.

+0

Ciò che manca a ArrayList è un supporto efficiente per le primitive, l'operatore [], crea due oggetti (il ArrayList e Object []) quando ne hai bisogno solo uno. –

3

Sì. Ma io sono dell'opinione che lo Java non dovrebbe avere nessuna primitiva. Penso che i primitivi in ​​Java siano una rottura dalla pulizia del linguaggio. Tutto in Java dovrebbe essere oggetti. o meno gli oggetti vengono allocati sulla pila o mucchio dovrebbe essere un attuazione dettaglio della JVM non un costrutto del linguaggio. Ma penso che la mia opinione potrebbe essere più radicale di molti altri.

Prima di attivare l'autoboxing, occuparsi di oggetti primitivi e oggetti era molto macchinoso.

Se le matrici erano oggetti e potrebbe essere autoboxed (e generisized!), Potremmo avere qualcosa di simile

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

Concordo sul fatto che i primitivi che non possono essere trattati in modo trasparente come oggetti siano sfortunati. Il compilatore/JVM dovrebbe essere in grado di risolverlo. ArrayUtils ha due metodi toObject() e toPrimitive(). Potrebbe avere un altro metodo per cambiare il tipo di array. –

+0

Suggerirei che gli array e Integer [] fossero due modi di scrivere la stessa cosa. ;) –

+0

È troppo tardi per sistemare cose come queste in Java. Dai un'occhiata alle lingue in cui hanno fatto parte del design sin dall'inizio. Ad esempio in Scala tutto è un oggetto. –

5

Tali metodi iniziano a guardare un sacco come Ruby o Python idiomi. Sfortunatamente non puoi farlo in java (vorrei che tu potessi).

Per uno, come altri hanno sottolineato, le classi di collezioni lo fanno per voi. Per un altro, myarray.sort() non è così bello perché è possibile creare array di oggetti per i quali l'ordinamento non è stato definito. Supponiamo di avere

Foo[] foos; 

E Foo non è paragonabile. Cosa succede su foos.sort()?Abbiamo sicuramente non vorremmo averlo funzionare solo per le primitive

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

e certamente non poteva avere il compilatore consentire solo la sintassi per gli oggetti analoghi. E una volta che si arriva a qualcosa come

myarray.add(new Foo()); 

è una specie di inutile, come array in Java non sono growable.

E sarebbe bello se la stampa di una matrice non ti ha dato che inutile

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

spazzatura, però.

+0

ArrayUtils.add(), addAll() e remove() restituisce una nuova matrice con l'elemento aggiunto. –

+0

Questi metodi sono molto utili per la gestione di un array quando non si desidera sovraccaricare un ArrayList. –

0

Per coloro che hanno perso un post precedente che è stato chiuso. Alcuni altri esempi includono

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

Lo copio nella domanda come addendum, Peter. Gli array – paxdiablo

2

Prima di rispondere PER DOVREBBE, ti dirò lo stato di questo problema.

In Java, gli array sono considerati oggetti: è possibile memorizzarli in un elenco, ad esempio. Tuttavia sono oggetti speciali in quanto ereditano da Object ma non sono istanziati o accessibili con la stessa sintassi (grazie per la correzione Peter). Sono ottimizzati in modo aggressivo dalla JVM per ovvi problemi di prestazioni, e quindi il modo in cui un array viene archiviato dipende dall'implementazione.

Quindi l'argomento Sun sarebbe che, se fornissero un oggetto API per l'array, potrebbe richiedere l'installazione di hardware, software o altre caratteristiche specifiche.

L'unica vera interfaccia per gli array è il metodo statico System.arrayCopy o Array. * Metodi statici, che copieranno in modo più efficiente da/verso gli array.

In risposta a DOVREBBE; è stato risolto, anche se uno standard sarebbe migliore della risposta: usa ArrayList.

+0

implementano solo il metodo clone(), tutti gli altri metodi sono ereditati da Object. Non che non siano implementati/disponibili. Loro sono. Tutti loro. –

2

Sì, credo che gli array debbano avere un'API definita oltre a quella specificata nella lingua stessa. In particolare, è fastidioso che un Foo[] non implementa Iterable<Foo>. Sì, lo so che è facile da avvolgere - ma è fastidioso che tu debba farlo.

.NET ottiene questo principalmente, con il tipo Array che è principalmente per l'accesso non generico e varie interfacce generiche che si ritiene siano implementate dagli array effettivi. Per esempio:

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

(Aiuta che i generici .NET far fronte con i tipi primitivi meglio di Java fa.)

L'unica nota stonata che ho visto di questo approccio è che gli array possono essere covarianti in .NET , ma i generici normali non lo sono e le cose si confondono leggermente con gli array basati su zero e gli array rettangolari.

Per inciso, varie persone hanno fatto riferimento alle matrici come primitive in questo thread. Sebbene abbiano certamente un trattamento speciale, non sono definiti come primitivi. Dal language spec, section 4.2:

un tipo primitivo è predefinito dal linguaggio di programmazione Java e prende il nome dal suo parola chiave riservata (§3.9):

 
PrimitiveType: 
     NumericType 
     boolean 

NumericType: 
     IntegralType 
     FloatingPointType 

IntegralType: one of 
     byte short int long char 

FloatingPointType: one of 
     float double 
1

Credo che questo è molto difficile da realizzare senza rompere la compatibilità a molti livelli.

  • JVM tratta gli array in modo leggermente diverso rispetto ad altri oggetti. La creazione/inizializzazione è diversa: nessun costruttore è chiamato per una cosa. Come vorresti aggiungere nuovi metodi? Se aggiungendo la superclasse, chiameresti il ​​suo costruttore?
  • Gli array conoscono il tipo di elemento in runtime, i generici no. Se volessi aggiungere una nuova superclasse per tutti gli array (come hai suggerito nella domanda originale), la renderebbe generica? Inoltre, tieni presente che gli array sono covarianti in Java, i generici no.
  • Le matrici hanno risolto un insieme di metodi/campi specificati nella specifica del linguaggio Java (tutti i metodi da Oggetti, che sono esplicitamente denominati in JLS, campo lunghezza). L'aggiunta di nuovi membri potrebbe rompere i client esistenti a seconda di ciò. (Vale a dire gli array non sono la vostra classe Random)
  • Array serializzazione sarebbe probabilmente influenzato troppo
  • Sono sicuro che ci sono ulteriori dettagli di implementazione che renderebbe questo estremamente difficile :-(
  • programmi compilati a lavorare con nuovi metodi sarebbe non funzionano su JVM anziani. Quel che è peggio, a seconda realizzazione, programmi compilati per il vecchio JVM potrebbero non funzionare con gli array modificati sulle nuove JVM.

Vorrei avere i metodi direttamente in "classe Array", I don' Penso che sia possibile implementarlo ora.

1

Personalmente mi piace l'idea che tutto sia un oggetto, e questo è già stato fatto in smalltalk, ad esempio. Tuttavia, le conseguenze di rendere tutto, persino i metodi/le funzioni di un oggetto sono di vasta portata (date un'occhiata a smalltalk per vedere cosa intendo). Essere coerenti nell'applicazione del "tutto è un oggetto" - risultati risultati in un linguaggio che non assomiglia più a C (o Java).

Java è stato progettato in modo molto consapevole per essere accessibile ai programmatori C, e ci è riuscito, ma in realtà non è molto orientato agli oggetti rispetto al smalltalk. È un'eredità come una variante di C che si manifesta dappertutto, come negli array e il fatto che ci siano dei primitivi.

Quindi, per rispondere alla domanda di DOVREBBE, direi di no, perché Java non sarebbe più Java con quel cambiamento. Come altri hanno sottolineato, esistono altre classi che consentono di gestire attività che potrebbero essere state eseguite con un array in C utilizzando oggetti in Java, ma eliminare tutti i tipi di dati primitivi e gli array è un compito meglio lasciato a una lingua diversa , A PARER MIO.

0

Una ragione credo che non sarebbe così difficile è che è possibile aggiungere metodi indirettamente modificando Object (Un vero e proprio trucco Sono d'accordo, ma si vede che funziona) Con l'aggiunta di metodi per oggetto, il seguente codice

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

Stampe

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

questo funziona con Java 5 & 6 e sia il compilatore e IDE gestito questo come mi aspettavo.