2012-07-19 20 views
7

que estoy tratando de hacer una llamada a un método como este,Como llegar clase con tipos genéricos en Java

public class GenericsTest<T> { 

    public static <T> Map<String, T> createMap(Class<? extends Map<String, T>> clazz) { 
     return null; 
    } 

    public static void main(String[] argv) { 
     Map<String, Integer> result = createMap(TreeMap.class); 
    } 
} 

Pero estoy recibiendo este error,

<T>createMap(java.lang.Class<? extends java.util.Map<java.lang.String,T>>) in test.GenericsTest<T> cannot be applied to (java.lang.Class<java.util.TreeMap>) 

Cómo solucionar este problema?

+0

No se puede debido a borrado de tipo. En particular, la firma del método no tiene sentido porque está tratando de sacar 'T' aunque está tomando una 'Clase' para un 'Mapa' con el parámetro de valor como' T'. Nunca podrá obtener el tipo anidado sin una instancia existente del objeto. (Podría pasar '(nuevo HashMap ()). GetClass()', pero aún no podrá recuperar 'Integer' de ese método). – pickypg

+0

CreateMap() es de una biblioteca que usamos. Debe haber una forma de llamar a ese método. –

+0

Cuestiono la legitimidad del objeto devuelto. Supuestamente está devolviendo una instancia del parámetro de valor, 'T', cuando se pasa en la' Clase' para un 'Mapa', y el nombre del método es' createMap'. Nada de esto tiene sentido. – pickypg

Respuesta

3
Map<String, Integer> instance = new TreeMap<String, Integer>(); 

@SuppressWarnings("unchecked") 
Map<String, Integer> map = 
    createMap((Class<? extends Map<String, Integer>>)instance.getClass()); 

map.put("x", 1); 

System.out.println("THIS IS x: " + map.get("x")); 

Esto imprimirá apropiadamente a cabo 1. La aplicación del método es más probable

try 
{ 
    return clazz.newInstance(); 
} 
catch (Exception e) 
{ 
    throw new RuntimeException(e); 
} 

Una mejor aplicación de su API sería para ellos para preguntar por el tipo, T, y para para devolver un Map de su elección en lugar de pedirle todos los detalles. De lo contrario, siempre y cuando no se están llenando en el Map con cualquier dato, se puede crear una instancia de un Map con el argumento de tipo genérico a sí mismo de esta manera:

public static <T> Map<String, T> getMap() 
{ 
    return new TreeMap<String, T>(); 
} 

luego podrás acceder a que sin una advertencia:

// note the lack of type arguments, which are inferred 
Map<String, Integer> instance = getMap(); 

// alternatively, you could do it more explicitly: 
// Map<String, Integer> instance = ClassName.<Integer>getMap(); 

realmente no hay razón para que se pedirá el tipo de su Map excepto Class para darle vuelta una coincidencia exacta con la aplicación (por ejemplo, si usted se pega en un HashMap, por lo que recibirá de vuelta una HashMap, y si te quedas en un TreeMap, luego recibirá un TreeMap). Sin embargo, sospecho que el TreeMap perderá cualquier Comparator con el que se haya construido y, dado que se trata de un campo inmutable (final) de TreeMap, no se puede reparar; eso significa que el Map no es el mismo en ese caso, ni es probable que sea lo que usted desea.

Si están llenando el Map con datos, entonces tiene aún menos sentido. Siempre puede pasar una instancia de Map para completar, o hacer que devuelvan un Map que simplemente puede ajustar (por ejemplo, new TreeMap<String, Integer>(instance);), y deben saber qué Map ofrece la mayor utilidad a los datos.

+0

Esto se ejecuta pero con la advertencia no marcada. Debe haber una forma de llamar a este método sin previo aviso. Ese es el propósito de usar genéricos. –

+0

Tiene razón sobre el propósito, pero Java tiene genéricos limitados debido a Type Erasure, que está causando este problema; hay limitaciones a lo que puede hacer sin tener que convencer al compilador para que lo haga por usted. Probablemente sea la característica que menos me gusta de Java porque será la más difícil de solucionar o reemplazar. .NET tiene un sistema genérico mucho más versátil porque no se olvida en el tiempo de ejecución. Después de la compilación, el acceso al mapa se convertirá en '(Entero) map.get (" x ")' porque el tipo devuelto es en realidad 'Objeto'. – pickypg

Cuestiones relacionadas