Sprawdź, czy obiekt jest wystąpieniem typu parametru


86

Czy istnieje sposób określenia, czy obiekt jest instancją typu ogólnego?

public <T> test(Object obj) {
    if (obj instanceof T) {
        ...
    }
}

To oczywiście nie działa. Czy jest alternatywa? Tak jak chcę użyć odbicia Java, aby utworzyć wystąpienie klasy, a następnie sprawdzić, czy jest to typ ogólny T.

Odpowiedzi:


128

Jedynym sposobem, w jaki możesz to sprawdzić, jest posiadanie Classobiektu reprezentującego typ:

Class<T> type; //maybe passed into the method
if ( type.isInstance(obj) ) {
   //...
}

Jeśli nie chcesz otrzymywać typejako parametru metody, być może chcesz go zainicjalizować:Class type = ((T) new Object()).getClass();
JordiVilaplana

9
@JordiVilaplana To nie jest w porządku, da ci java.lang.Object jako klasę. Zobacz to: ideone.com/bxt9Jq
Sri Harsha Chilakapati

3
Użyj:Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Ton Snoei

22

Aby rozszerzyć próbkę Marka Petersa, często chcesz zrobić coś takiego:

Class<T> type; //maybe passed to the method
if ( type.isInstance(obj) ) {
   T t = type.cast(obj);
   // ...
}

11

Jeśli nie chcesz przekazywać typu klasy jako parametru, o czym wspomniał Mark Peters, możesz użyć następującego kodu. Uznanie dla Davida O'Meary.

  Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
                  .getActualTypeArguments()[0];
  if (type.isInstance(obj)) {
      ...
  }

5
DajeType safety: Unchecked cast from Type to Class<T>
Marco Sulla

5

Możesz tego spróbować

// Cast your object to the generic type.
T data = null;
try {
    data = (T) obj;
} catch (ClassCastException cce) {
    // Log the error.
}

// Check if the cast completed successfully.
if(data != null) {
    // whatever....
}

7
To nie działa! Obsada kończy się sukcesem dla wszystkich typów. Dlatego wyświetla ostrzeżenie o kompilacji „Niezaznaczone rzutowanie”.
Lii

3

Bardziej sensowne byłoby nałożenie ograniczenia na to, gdzie typ Tjest używany do parametryzacji Classtypu. Kiedy podajesz typ, zamiast używać czegoś takiego Class<?>, powinieneś użyć Class<? extends T>.


1
Jeśli chcesz poznać dokładny typ T w czasie wykonywania, ważne jest, aby żądać, aby wywołujący przechodził w Class <T>, a nie Class <? wydłuża T>. Na przykład kod Puce'a nie skompilowałby się z Class <? rozszerza T>.
Theodore Murdock

1

To zadziała (częściowo) tylko wtedy, gdy masz obiekt typu T. Następnie możesz uzyskać klasę tego obiektu, zobaczyć java.lang.Class<T>i sprawdzić, czy jest taka sama jak przedmiot, o którym mowa.

Ale zauważ, że jest to sprzeczne z samym powodem, dla którego mamy genetyki: używanie typu ogólnego jest sposobem na powiedzenie, że nie obchodzi cię, jaki to naprawdę typ (do górnej i dolnej granicy, którą można określić).


Nie ma gwarancji, że Class <?> Zwrócone z wywołania .getClass () w instancji T innej niż null nie jest klasą Class <T>. Najlepsze, co możesz zagwarantować, to to, że jest to klasa <? rozszerza T>.
Theodore Murdock
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.