2011-09-08 10 views
5

Hola tengo un método que debería devolver resultados diferentes según el tipo.¿Comprobar instancia de genérico?

Puedo hacer esto para verificar el tipo genérico.

public <T> T search(final String query){ 
T returnValue = null; 
if (returnValue instanceof String){ } 
if (returnValue instanceof Integer){ } 
if (returnValue instanceof MyObject){ } 

¿Pero por qué no puedo hacer algo así?

public <T> T search(final String query){ 
T returnValue = null; 
if (T instanceof String){ } 
if (T instanceof Integer){ } 
if (T instanceof MyObject){ } 

Código de llamada.

String id = myObjcet.<String> search("select ..."); 

Respuesta

4

Java implementa genéricos "por borrado". Eso significa que en tiempo de ejecución no hay (casi) ningún conocimiento de genéricos en absoluto. En cambio, el compilador busca genéricos, pero bajo la cubierta convierte todo en Objeto (o en el límite genérico más cercano).

Si descompilar ese método usando javap, verá que se lee:

public Object search(... 

se retira Toda referencia a T.

Ésta es una limitación grave de los genéricos en Java, que a menudo se refleja también en las clases JRE con construcciones como:

SomeClass<String> x = new SomeClass<String>(String.class); 

Cuando se necesita la tercera repetición de la cadena (String.class) porque el constructor necesita saber en qué clase está operando.

Este paradigma, a pesar de ser horrible, podría resolver su problema.

Las informaciones sobre genéricos están en realidad contenidas en los archivos .class, como metadatos, se pueden inspeccionar mediante reflexión y hasta cierto punto también se pueden resolver. Sin embargo, esto no es posible en un caso como el suyo, pero es usado, por ejemplo, por los ORM en buscadores de listas. por ejemplo, usando Hibernate, un captador de esta manera:

public List<Group> getGroups() { 

pueden ser inspeccionados por Hibernate para que sepa que la lista se supone que debe contener instancias de Grupo, adaptando sus consultas en consecuencia.

(Sin embargo, incluso si los genéricos no se implementan de esta manera, T no es una instancia, es una clase, escribir String instanceof String es igualmente incorrecto. Debería ser if (T.equals (String.class)))

+0

Muchas gracias por esta espléndida explicación, aceptaré su respuesta tan pronto como SO me lo permita. – Farmor

1

Porque T se borra durante la ejecución. Está solo allí en tiempo de compilación. returnValue es la variable, está presente en el tiempo de ejecución.

1
public <T> T search(Class<T> clazz, String query){ 
T returnValue = null; 
if (clazz==String.class){ } 
if (clazz==Integer.class){ } 
if (MyObject.clazz.isAssignableFrom(clazz){ } 


String id = myObjcet.search(String.class, "select ..."); 
Cuestiones relacionadas