2015-04-01 8 views
8

Stavo seguendo conferenze di Algorithms su Coursera di Robert Sedgewick. Ero un po 'confuso quando Mr.Robert ha sottolineato che non è possibile utilizzare Generics con Arrays poiché non è consentito. Ma ArrayList nella Collezione Framework utilizza Array internamente e tipi di dati generici sono allowed.I vuol dire che siamo in grado di fare quanto segue:In che modo ArrayList è rappresentato internamente in Java Collection Framework.?

ArrayList<Integer> list = new ArrayList<Integer>(); 

Un mod ha sottolineato era questo:

public class FixedCapacityStack<Item>{ 
    private Item[] s; 
    private int N = 0; 

public FixedCapacityStack(int capacity) 
{ s = (Item[]) new Object[capacity];} //this hack 

Ha anche ho detto che questo è un brutto trucco e deve essere evitato e produce anche avvertimenti durante la compilazione.

mia domanda è:

1.) Come funziona ArrayList quindi rappresentare internamente vari tipi Generics?

2.) Se (si presume) usano l'hack sopra menzionato perché non genera un avviso quando compiliamo un programma con ArrayList?

3.) Esiste un modo migliore a parte il cast precedente?

+1

questo può aiutare: http://docs.oracle.com/javase/tutorial/java/generics/erasure.html – tony200910041

+2

Puoi anche guardare la fonte: http://grepcode.com/file/repository.grepcode .com/java/root/jdk/openjdk/7u40-b43/java/util/ArrayList.java/ – user432

+0

'FixedCapacityStack' non sembra essere presente nel codice sorgente' ArrayList' (collegato nel commento precedente) - era questo un esempio delle lezioni invece? – DNA

risposta

2

Per la fonte:

1-ArrayList memorizza elementi in un Object[], e getta il valore durante il recupero di singoli elementi. In realtà c'è uno @SuppressWarnings("unchecked") dove avviene il cast.

2 - Due risposte qui: la prima è che non si sta compilando (in genere) ArrayList, ma è sufficiente includerlo nel classpath da rt.jar in JRE/JDK. Il secondo è che ArrayList utilizza uno @SuppressWarnings per la conversione non controllata da Object al tipo generico.

3 - Il vostro altra alternativa ("migliore" è del tutto soggettiva) sarebbe quello di richiedere l'Class per il tipo generico e utilizzare Array.newInstance(Class clazz, int capacity) per creare l'array, come descritto nella this question

+0

Non capisco. perché non può funzionare? –

+0

@MustafaUjjainwala Perché getterà un 'ClassCastException' come ha detto. – EJP

+2

Funzionerà, 'Item []' viene cancellato su 'Object []' in fase di esecuzione. – Alex

1

1.) Come ArrayList quindi rappresenta internamente vari tipi di Generics?

Cosa intendi "internamente"? I generici esistono solo al momento della compilazione. ArrayList è già stato compilato da qualcun altro per te e stai semplicemente utilizzando il file di classe. Quindi non ci sono generici lì.

Diverse implementazioni di librerie Java potrebbero scrivere la sorgente in modo diverso, ma ciò non vi riguarda. Quello che fa "internamente" è un dettaglio di implementazione interno di cui un utente della classe non dovrebbe preoccuparsi.

Se si dovesse scrivere la propria classe come FixedCapacityStack, allora si potrebbe farlo in diversi modi:

  • Si potrebbe fare la cosa in cui s è di tipo Item[] come avete mostrato in precedenza, e si crea un Object[] e cast al Item[]
  • Oppure si può fare s di tipo Object[] e gettato a digitare Item quando si ottiene elementi fuori di esso

Nota che entrambi gli approcci sono gli stessi dopo la cancellazione, quindi entrambi verranno compilati allo stesso bytecode. La differenza è solo lo stile al momento della compilazione.

Il vantaggio del primo approccio rispetto al secondo è che quando si ottengono elementi da esso, è già il tipo giusto, quindi non si dispone di tutti questi cast uguali ovunque. Lo svantaggio del primo approccio è che il cast iniziale da Object[] a Item[] è fondamentalmente una "bugia" e funzionerà solo se si è assolutamente certi di non esporre s all'esterno della classe (ad esempio non si dispone di un metodo che restituisce s come tipo Item[]); altrimenti si avranno eccezioni del cast di classe in luoghi imprevisti.

2.) Se (si presume) usano l'hack sopra menzionato perché non genera un avviso quando compiliamo un programma con ArrayList?

Ci sarebbe solo un avviso quando effettivamente compila questa classe. Ma non se fosse già compilato e stai semplicemente usando il file di classe. In realtà, di solito non hai nemmeno la fonte di ArrayList.

3.) Esiste un modo migliore a parte il cast precedente?

Dipende da cosa intendi per "migliore". Ho mostrato i due approcci e i vantaggi e gli svantaggi di ciascuno.

Problemi correlati