Testen Sie, ob das Objekt eine Instanz eines Parametertyps ist

82

Gibt es eine Möglichkeit festzustellen, ob ein Objekt eine Instanz eines generischen Typs ist?

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

Das funktioniert eindeutig nicht. Gibt es eine Alternative? Als ob ich Java Reflection verwenden möchte, um eine Klasse zu instanziieren und dann zu überprüfen, ob sie vom Typ generic ist T.

Nikordaris
quelle

Antworten:

125

Die einzige Möglichkeit, diese Prüfung durchzuführen, besteht darin, dass das ClassObjekt den Typ darstellt:

Class<T> type; //maybe passed into the method
if ( type.isInstance(obj) ) {
   //...
}
Mark Peters
quelle
Wenn Sie nicht typeals Methodenparameter erhalten möchten, möchten Sie ihn möglicherweise initialisieren:Class type = ((T) new Object()).getClass();
JordiVilaplana
9
@JordiVilaplana Das ist nicht richtig, es gibt dir java.lang.Object als Klasse. Überprüfen Sie dies heraus: ideone.com/bxt9Jq
Sri Harsha Chilakapati
3
Verwenden Sie:Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Ton Snoei
20

Um die Stichprobe von Mark Peters zu erweitern, möchten Sie häufig Folgendes tun:

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

Wenn Sie den Klassentyp nicht wie von Mark Peters erwähnt als Parameter übergeben möchten, können Sie den folgenden Code verwenden. Ein großes Lob an David O'Meara.

  Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
                  .getActualTypeArguments()[0];
  if (type.isInstance(obj)) {
      ...
  }
Ton Snoei
quelle
5
Es gibtType safety: Unchecked cast from Type to Class<T>
Marco Sulla
5

Sie könnten dies versuchen,

// 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....
}
George Siggouroglou
quelle
7
Das funktioniert nicht! Die Besetzung ist für alle Typen erfolgreich. Aus diesem Grund wird eine Kompilierungswarnung "Unchecked cast" ausgegeben.
Lii
3

Es wäre sinnvoller, die Einschränkung festzulegen, wo der Typ Tzur Parametrisierung des ClassTyps verwendet wird. Wenn Sie den Typ übergeben Class<?>, sollten Sie ihn verwenden , anstatt so etwas zu verwenden Class<? extends T>.

Chris Dennett
quelle
1
Wenn Sie zur Laufzeit den genauen Typ von T kennen möchten, ist es wichtig, dass der Anrufer eine Klasse <T> und keine Klasse <? erweitert T>. Zum Beispiel würde Puce's Code nicht mit Class <? Kompiliert. verlängert T>.
Theodore Murdock
1

Dies funktioniert nur (teilweise), wenn Sie ein Objekt vom Typ T haben. Dann können Sie die Klasse dieses Objekts abrufen, sehen java.lang.Class<T>und herausfinden, ob es mit dem betreffenden Objekt identisch ist.

Beachten Sie jedoch, dass dies genau dem Grund widerspricht, warum wir Genrics haben: Die Verwendung eines generischen Typs ist eine Möglichkeit zu sagen, dass es Ihnen egal ist, um welchen Typ es sich tatsächlich handelt (bis zu den oberen und unteren Grenzen, die angegeben werden können).

Ingo
quelle
Es wird nicht garantiert, dass die von einem .getClass () -Aufruf für eine Nicht-Null-T-Instanz zurückgegebene Klasse <?> Eine Klasse <T> ist. Das Beste, was Sie garantieren können, ist, dass es sich um eine Klasse <handelt. erweitert T>.
Theodore Murdock