Originariamente inviato da doping
Ciao a tutti, ho 1 problema, non riesco a creare un array di oggetti da me creati, insomma ho creato una classe mia di nome PositionSequence<E> e devo creare un array di oggetti di questo tipo, purtroppo però ho un eccezzione di questo tipo:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LSequenza.PositionSequence;
Qui c'è da entrare nei "meandri" più complicati dei "generics". Partiamo dall'inizio.
Per via della ben nota "erasure", il tipo PositionSequence<E> non è un tipo "reifiable" (reificabile), motivo per cui non è possibile creare un array di questo tipo. Per dirla con del codice:
PositionSequence<E>[] arr = new PositionSequence<E>[100]; // ERRORE
non è possibile, è un "generic array creation" e viene segnalato come errore dal compilatore.
La tua riga che rimodello qui per semplicità:
PositionSequence<E>[] arr = (PositionSequence<E>[]) new Object[100];
dal punto di vista della compilazione è accettata, salvo un "unchecked warning" sempre per via della erasure (il cast non è controllabile né in compilazione né a runtime perché in nessuno dei due casi si può sapere cosa sarà quel 'E').
Ma il fatto è che se un array viene creato proprio di tipo Object[] non può essere di certo un PositionSequence[] quindi il cast fallisce a runtime.
La soluzione più semplice e pratica è quella di usare una collezione (es. ArrayList) invece di un array.
Esempio:
codice:
class ArrPosSeq<E>
{
ArrayList<PositionSequence<E>> arrList;
public ArrPosSeq ()
{
arrList = new ArrayList<PositionSequence<E>> ();
}
public void add (PositionSequence<E> ps)
{
arrList.add (ps);
}
}
Poi per usarlo, ad esempio:
codice:
ArrPosSeq<Integer> aps = new ArrPosSeq<Integer> ();
PositionSequence<Integer> psint = new PositionSequence<Integer> ();
aps.add (psint);
Questo evita i problemi citati all'inizio ed elimina gli unchecked warning.
Un'altra soluzione è quella di creare l'array proprio come Object[] e di fare un cast (unchecked) a PositionSequence<E> dove serve.
Esempio:
codice:
class ArrPosSeq<E>
{
Object[] arr;
int pos;
public ArrPosSeq ()
{
arr = new Object[100];
}
public void add (PositionSequence<E> ps)
{
arr[pos++] = ps;
}
public PositionSequence<E> get (int index)
{
return (PositionSequence<E>) arr[index]; // unchecked cast ma ok a runtime
}
}
Un array di Object può contenere reference a qualunque cosa .... quindi anche a tipi PositionSequence<E>.
Un'ulteriore soluzione è una leggera variante di quella appena detta. Invece di usare come tipo dell'array Object si usa PositionSequence ovvero si usa il "raw type" di PositionSequence<E>.
codice:
class ArrPosSeq<E>
{
PositionSequence[] arr;
int pos;
public ArrPosSeq ()
{
arr = new PositionSequence[100];
}
public void add (PositionSequence<E> ps)
{
arr[pos++] = ps;
}
public PositionSequence<E> get (int index)
{
return (PositionSequence<E>) arr[index]; // unchecked cast ma ok a runtime
}
}
Internamente cambia poco e visto dall'esterno nulla.
Come hai potuto vedere, sei appena andato a "cozzare" contro una delle parti più complesse ed oscure dei generics. Quindi prima di partire in quinta con quello che stavi facendo, valuta bene cosa fare e se è la scelta giusta.