Generici Java:Confrontando la classe dell'Oggetto o con <E>
Domanda
Diciamo che ho la seguente classe:
public class Test<E> {
public boolean sameClassAs(Object o) {
// TODO help!
}
}
Come potrei verificarlo? o
è la stessa classe di E
?
Test<String> test = new Test<String>();
test.sameClassAs("a string"); // returns true;
test.sameClassAs(4); // returns false;
Non riesco a modificare la firma del metodo da (Object o)
poiché sto sovrascrivendo una superclasse e quindi non posso scegliere la firma del mio metodo.
Preferirei inoltre non tentare un cast e quindi rilevare l'eccezione risultante se fallisce.
Soluzione
Un'istanza di Test
non ha informazioni su cosa E
è in fase di esecuzione.Quindi, devi superare a Class<E>
al costruttore di Test.
public class Test<E> {
private final Class<E> clazz;
public Test(Class<E> clazz) {
if (clazz == null) {
throw new NullPointerException();
}
this.clazz = clazz;
}
// To make things easier on clients:
public static <T> Test<T> create(Class<T> clazz) {
return new Test<T>(clazz);
}
public boolean sameClassAs(Object o) {
return o != null && o.getClass() == clazz;
}
}
Se vuoi una relazione "istanza di", usa Class.isAssignableFrom
invece del Class
confronto.Nota, E
dovrà essere un tipo non generico, per lo stesso motivo Test
ha bisogno del Class
oggetto.
Per esempi nell'API Java, vedere java.util.Collections.checkedSet
e simili.
Altri suggerimenti
Il metodo che ho sempre utilizzato è riportato di seguito.È doloroso e un po' brutto, ma non ne ho trovato uno migliore.È necessario passare il tipo di classe durante la costruzione, poiché quando i generici vengono compilati, le informazioni sulla classe vengono perse.
public class Test<E> {
private Class<E> clazz;
public Test(Class<E> clazz) {
this.clazz = clazz;
}
public boolean sameClassAs(Object o) {
return this.clazz.isInstance(o);
}
}
Potrei solo farlo funzionare in questo modo:
public class Test<E> {
private E e;
public void setE(E e) {
this.e = e;
}
public boolean sameClassAs(Object o) {
return (o.getClass().equals(e.getClass()));
}
public boolean sameClassAs2(Object o) {
return e.getClass().isInstance(o);
}
}
Stavo solo cercando di fare la stessa cosa, e un bel trucco che ho appena realizzato è che puoi provare un cast e, se il cast fallisce, verrà lanciata ClassCastException.Puoi prenderlo e fare qualunque cosa.
quindi il tuo metodo sameClassAs dovrebbe assomigliare a:
public boolean sameClassAs(Object o) {
boolean same = false;
try {
E t = (E)o;
same = true;
} catch (ClassCastException e) {
// same is false, nothing else to do
} finally {
return same;
}
}