Prueba si el objeto es una instancia de un tipo de parámetro

83

¿Hay alguna forma de determinar si un objeto es una instancia de un tipo genérico?

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

Eso claramente no funciona. ¿Existe alguna alternativa? Quiero usar la reflexión de Java para crear una instancia de una clase y luego verificar que sea de tipo genérico T.

Nikordaris
fuente

Respuestas:

125

La única forma en que puede hacer esta verificación es si tiene el Classobjeto que representa el tipo:

Class<T> type; //maybe passed into the method
if ( type.isInstance(obj) ) {
   //...
}
Mark Peters
fuente
Si no desea obtener typecomo parámetro de método, tal vez desee inicializarlo:Class type = ((T) new Object()).getClass();
JordiVilaplana
9
@JordiVilaplana Eso no es correcto, te dará java.lang.Object como clase. Mira esto: ideone.com/bxt9Jq
Sri Harsha Chilakapati
3
Uso:Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Ton Snoei
20

Para ampliar la muestra de Mark Peters, a menudo desea hacer algo como:

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

Si no desea pasar el tipo de clase como parámetro como lo menciona Mark Peters, puede usar el siguiente código. Felicitaciones a David O'Meara.

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

Podrías intentar esto

// 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
fuente
7
¡Esto no funciona! El elenco tiene éxito para todos los tipos. Es por eso que da una advertencia de compilación "Unchecked Cast".
Lii
3

Tendría más sentido restringir dónde Tse usa el Classtipo para parametrizar el tipo. Cuando pasa el tipo, en lugar de usar algo como Class<?>, debe usar Class<? extends T>.

Chris Dennett
fuente
1
Si desea saber el tipo exacto de T en tiempo de ejecución, es importante exigir que la persona que llama pase una Clase <T>, no una Clase <? extiende T>. Por ejemplo, el código de Puce no se compilaría con Class <? extiende T>.
Theodore Murdock
1

Esto solo funcionará (en parte) si tiene un objeto de tipo T. Entonces puede obtener la clase de ese objeto, consulte java.lang.Class<T> y encontrar si es el mismo que el objeto en cuestión.

Pero tenga en cuenta que esto va en contra de la razón por la que tenemos genrics: usar un tipo genérico es una forma de decir que no le importa qué tipo es realmente (hasta los límites superior e inferior que se pueden especificar).

Ingo
fuente
No se garantiza que la clase <?> Devuelta de una llamada .getClass () en una instancia T no nula sea una clase <T>. Lo mejor que puede garantizar es que es un Class <? extiende T>.
Theodore Murdock