Dwie opcje sprawdzania typu w czasie wykonywania za pomocą typów ogólnych:
Opcja 1 - Zepsuć konstruktora
Załóżmy, że nadpisujesz indexOf (...) i chcesz sprawdzić typ tylko pod kątem wydajności, aby zaoszczędzić sobie iterowania całej kolekcji.
Stwórz brudnego konstruktora, takiego jak ten:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
Następnie możesz użyć isAssignableFrom, aby sprawdzić typ.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
Za każdym razem, gdy tworzysz instancję obiektu, musiałbyś się powtarzać:
new MyCollection<Apples>(Apples.class);
Możesz zdecydować, że to nie jest tego warte. W implementacji ArrayList.indexOf (...) nie sprawdzają, czy typ jest zgodny.
Opcja 2 - Niech to zawiedzie
Jeśli potrzebujesz metody abstrakcyjnej, która wymaga nieznanego typu, to wszystko, czego naprawdę chcesz, to aby kompilator przestał płakać z powodu instancji . Jeśli masz taką metodę:
protected abstract void abstractMethod(T element);
Możesz go używać w ten sposób:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
Rzucasz obiekt na T (twój typ ogólny), aby oszukać kompilator. Twoje rzutowanie nic nie robi w czasie wykonywania , ale nadal otrzymasz ClassCastException, gdy spróbujesz przekazać niewłaściwy typ obiektu do metody abstrakcyjnej.
UWAGA 1: Jeśli wykonujesz dodatkowe niezaznaczone rzuty w swojej metodzie abstrakcyjnej, Twoje ClassCastExceptions zostaną tutaj przechwycone. To może być dobre lub złe, więc przemyśl to.
UWAGA 2: Korzystając z instanceof . Ponieważ nie możesz go użyć, może być konieczne sprawdzenie wartości zerowej gołymi rękami.
Class.isAssignableFrom
.