In questo caso, è perfettamente corretto sopprimere l'avviso di cast non controllato.
È un cast non controllato perché E
non è noto in fase di runtime. Quindi il controllo del runtime può solo controllare il cast fino a Object[]
(la cancellazione di E[]
), ma non in realtà fino a E[]
stesso. Quindi, ad esempio, se E
era Integer
, se la classe di esecuzione effettiva dell'oggetto era String[]
, non verrebbe rilevata dal controllo anche se non è Integer[]
.)
Array.newInstance()
restituisce Object
e non E[]
(dove E
sarebbe l'argomento di tipo del parametro Class
), perché può essere utilizzato per creare entrambi gli array di primitive e matrici di riferimenti. Digitare variabili come E
non può rappresentare i tipi primitivi e l'unico supertipo di tipi di matrice primitiva è Object
. Gli oggetti Class
che rappresentano i tipi primitivi sono Class
parametrizzati con la sua classe wrapper come parametro type, ad es. int.class
ha tipo Class<Integer>
. Ma se passi int.class
a Array.newInstance()
, creerai un int[]
, non E[]
(che sarebbe Integer[]
). Ma se passi una Class<E>
che rappresenta un tipo di riferimento, Array.newInstance()
restituirà un E[]
.
Quindi, in sostanza, chiamando Array.newInstance()
con Class<E>
verrà sempre restituito un E[]
o una matrice di primitivi. Un tipo array-of-primitives non è un sottotipo di Object[]
, quindi fallirebbe un controllo di runtime per Object[]
. In altre parole, se il risultato è un Object[]
, è garantito che sia un E[]
. Quindi, anche se questo cast controlla solo fino a Object[]
in fase di esecuzione, e non controlla la parte da Object[]
a E[]
, in questo caso il controllo fino a Object[]
è sufficiente per garantire che è un E[]
, e quindi la parte non controllata non è un problema in questo caso, ed è effettivamente un cast completamente controllato.
A proposito, dal codice che hai mostrato, non è necessario passare un oggetto di classe per inizializzare GenSet
o usare Array.newInstance()
. Ciò sarebbe necessario solo se la tua classe usasse effettivamente la classe E
in fase di runtime. Ma non è così. Tutto ciò che fa è creare una matrice (che non è esposta all'esterno della classe) e ottenere elementi da essa. Questo può essere ottenuto utilizzando un Object[]
. Devi solo eseguire il cast su E
quando togli un elemento (che non è controllato da cui sappiamo essere al sicuro se mettiamo solo E
s):
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
this.a = new Object[s];
}
@SuppressWarnings("unchecked")
E get(int i) {
return (E)a[i];
}
}