Nel tentativo di comprendere Generics in Java (e come usarli), sto provando a implementare una struttura di lista che li usa ma hanno colpito un muro.
Scenario:
Supponiamo che ci siano alcune classi (le chiameremo ClassA, ClassB e ClassC) che estendono tutti ClassBase. ClassBase è astratto e contiene semplicemente un codice ID con getter e setter appropriati. Le sottoclassi aggiungono attributi aggiuntivi, ma questi non sono importanti.
L'elenco è progettato per essere in grado di contenere un numero delle sottoclassi di cui sopra e manipolare l'elenco utilizzando l'attributo ID comune. L'elenco deve essere disponibile e ogni elenco conterrà solo un tipo di sottoclasse (quindi un elenco di ClassA, ClassB o ClassC. Nessuna combinazione mista di questi).
Tentativo 1:
Ho impostato la mia classe List in questo modo:
ClassList<T extends ClassBase>
Quindi dichiaro un array di elementi come "private T list []" e scrivo il resto della classe. Le firme per i getter e setter di elementi sono le seguenti, poiché potrebbero essere importanti:
public T get(int index)
public void set(int index, T item)
Tutto sembra essere buono, tranne quando vado a compilare si lamenta di ogni istanza in cui provo a ricreare l'array sottostante (per ridurlo / ingrandirlo).
.\test\ListClass.java:10: error: generic array creation
list = new T[0];
^
Quindi dopo un po 'di riflessione e lettura l'errore ha senso, dato che il compilatore non sa quali costruttori saranno disponibili (almeno questo è il modo in cui lo capisco), quindi non sembra che in questo modo funzionerà.
Tentativo 2:
Conservo la stessa dichiarazione di classe, ma cambio l'array interno in "private ClassBase list []", e quindi adattare il mio codice di conseguenza. La modifica principale consiste nel trasmettere da ClassBase a T e viceversa quando necessario. Quindi il getter ad esempio si presenta così:
public T get(int index)
{
return (T)(list[index]);
}
Quindi ora il mio codice viene compilato ed eseguito, ma ogni istanza in cui ho eseguito il casting sopra riportato genera ora l'infame avviso non controllato:
.\test\ListClass.java:16: warning: [unchecked] unchecked cast
return (T)(list[index]);
^
Riesco a capire perché l'avvertimento appare, ma allo stesso tempo ListClass controlla tutti i mezzi per accedere e manipolare l'elenco, quindi posso garantire che solo gli elementi di tipo T siano posizionati lì.
Problema:
Suppongo di poter sopprimere gli avvertimenti. Ma sono convinto che siano lì per una ragione e preferirei sbarazzarci di loro nel modo giusto. Il problema è che non riesco a capire quale sia il modo "corretto" (o se in realtà il sopprimere l'errore è il modo corretto).
Questa è la mia domanda. Cosa c'è di sbagliato nel mio design e come lo risolvo?
Grazie in anticipo.
Nota:
Prima che qualcuno mi dica di usare uno dei generici esistenti e di smettere di reinventare la ruota, non è questo il punto. Il mio obiettivo non è quello di ricreare un sostituto per le liste generiche, è quello di capire i generici, e una lista come sopra riguarda il miglior esempio che riesco a pensare e che mostra chiaramente come funzionano.