Java: sicurezza di tipo - getto incontrollato
-
18-09-2019 - |
Domanda
Qui è il mio codice:
Object[] data = GeneComparison.readData(files);
MyGenome genome = (MyGenome) data[0];
LinkedList<Species> breeds = (LinkedList<Species>) data[1];
Si dà questo avvertimento per il LinkedList:
Type safety: Unchecked cast from Object to LinkedList<Species>
Perché si lamentano la lista collegata e non MyGenome?
Soluzione
Perché qui:
MyGenome genome = (MyGenome) data[0];
Non si utilizza farmaci generici
E qui
LinkedList<Species> breeds = (LinkedList<Species>) data[1];
Si sono in uso.
Questo è solo un avvertimento, si stia mescolando i tipi nella matrice dei dati. Se sai cosa stai facendo (voglio dire, se il secondo elemento fare contiene un LinkedList ) è possibile ignorare l'avviso.
Ma meglio sarebbe quello di avere un oggetto come questo:
class Anything {
private Object [] data;
public Anything( Object [] data ) {
this.data = data;
}
public Gnome getGnome() {
.....
}
public List<Species> getBreeds() {
......
}
}
E hanno a metodi che ritornano cose giuste, prima di una conversione corretta così si finisce con:
Anything anything = new Anything( GeneComparison.readData(files) );
MyGenome genome = anything.getGnome(); // similar to data[0]
LinkedList<Species> breeds = anything.getBreeds(); // similar to data[1];
All'interno quei metodi che devi fare trasformazioni appropriate.
Altri suggerimenti
Java si lamenta del genere quando lanci un tipo non-parametrizzato (Object) per un tipo parametrico (LinkedList). E 'per dirvi che potrebbe essere qualsiasi cosa. E 'molto diverso al primo cast ad eccezione del primo genererà un ClassCastException se non è quel tipo, ma il secondo non sarà.
Tutto si riduce al tipo di cancellazione. Una LinkedList in fase di esecuzione è in realtà solo un LinkedList. Si può mettere qualsiasi cosa in esso e non genererà un ClassCastException come il primo esempio.
Spesso per sbarazzarsi di questo avviso è necessario fare qualcosa di simile:
@SuppressWarning("unchecked")
public List<Something> getAll() {
return getSqlMapClient.queryForList("queryname");
}
dove queryForList () restituisce una lista (non parametrizzata) in cui si conosce il contenuto saranno di classe Qualcosa.
L'altro aspetto di questo è che gli array in Java sono covariante , nel senso che conservano rtti. Ad esempio:
Integer ints[] = new Integer[10];
Object objs[] = ints;
objs[3] = "hello";
sarà un'eccezione. Ma:
List<Integer> ints = new ArrayList<Integer>(10);
List<Object> objs = (List<Object>)ints;
objs.add("hello");
è perfettamente legale.