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];
}
}