Due opzioni per il controllo del tipo di runtime con generics:
Opzione 1: danneggia il costruttore
Supponiamo che tu abbia la precedenza su indexOf (...) e che desideri controllare il tipo solo per le prestazioni, per risparmiare te stesso iterando l'intera raccolta.
Crea un costruttore sporco come questo:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
Quindi è possibile utilizzare isAssignableFrom per verificare il tipo.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
Ogni volta che crei un'istanza del tuo oggetto, dovresti ripetere te stesso:
new MyCollection<Apples>(Apples.class);
Potresti decidere che non ne vale la pena. Nell'implementazione di ArrayList.indexOf (...) , non controllano che il tipo corrisponda.
Opzione 2 - Lascia che fallisca
Se devi usare un metodo astratto che richiede il tuo tipo sconosciuto, allora tutto ciò che vuoi davvero è che il compilatore smetta di piangere su instanceof . Se hai un metodo come questo:
protected abstract void abstractMethod(T element);
Puoi usarlo in questo modo:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
Stai lanciando l'oggetto su T (il tuo tipo generico), solo per ingannare il compilatore. Il tuo cast non fa nulla in fase di esecuzione , ma otterrai comunque ClassCastException quando proverai a passare il tipo di oggetto sbagliato nel tuo metodo astratto.
NOTA 1: se stai eseguendo ulteriori cast non controllati nel tuo metodo astratto, le ClassCastExceptions verranno catturate qui. Potrebbe essere buono o cattivo, quindi pensaci bene.
NOTA 2: si ottiene un controllo null gratuito quando si utilizza instanceof . Poiché non è possibile utilizzarlo, potrebbe essere necessario verificare la presenza di null a mani nude.
Class.isAssignableFrom
.