Pregunta

Tome la siguiente:

public Class<List<String>> getObjectType() {
    // what can I return here?
}

¿Qué clase de expresión literal puedo volver de este método que satisfaga los genéricos y compilar? List.class no se compilará, y tampoco se List.<String>class.

Si usted se pregunta "por qué", estoy escribiendo una implementación de FactoryBean<List<String>> de la primavera, lo que me obliga a poner en práctica Class<List<String>> getObjectType(). Sin embargo, esto es no una pregunta primavera.

editar:. Mis gritos lastimeros han sido escuchadas por los poderes fácticos de SpringSource, y así primavera 3.0.1 tendrá el tipo de retorno de getObjectType() cambió a Class<?>, lo que evita cuidadosamente el problema

¿Fue útil?

Solución

Siempre se puede echar a lo que necesita, como este

return (Class<List<String>>) new ArrayList<String>().getClass();

o

return (Class<List<String>>) Collections.<String>emptyList().getClass();

Pero supongo que eso no es lo que está después. Bien que funciona, con una advertencia, pero no es exactamente "hermosa".

Acabo de encontrar este

  

Por qué no hay clase literal para comodín tipos parametrizados?

     

Debido a que un tipo parametrizado comodín no tiene representación exacta de tipo en tiempo de ejecución.

Así fundición podría ser el único camino a seguir.

Otros consejos

Nunca se debe utilizar la Class<List<String>> constructo. No tiene sentido, y debe producir una advertencia en Java (pero no lo hace). instancias de clases siempre representan tipos primas, lo que puede tener Class<List>; Eso es. Si quieres algo para representar un tipo genérico cosificado como List<String>, se necesita una "señal de tipo super" como utiliza Guice:

http: //google-guice.googlecode. com / git / javadoc / com / google / inyección / TypeLiteral.html

La existencia de un Class<List<String>> es inherentemente peligroso. he aquí por qué:

// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok

System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
   unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning

for (int x: integerList) {
    // Compiles without warning, but throws ClassCastException at runtime
    System.out.println(100-x);
}

Encontrados este enlace en springframework.org que da una cierta penetración.

por ejemplo.

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();

Puede implementar ese método como este:

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}

Salida esta discusión en los foros sol:

http://forums.sun.com/thread.jspa?threadID=5253007

Y el blog de referencia que describe una solución alternativa mediante el uso de "fichas de tipo súper":

http://gafter.blogspot.com/2006/12 /super-type-tokens.html

No estoy seguro si esto es posible en absoluto, ya que será compilado cualquier clase literal a Class.forName(...) y puesto que esto ocurre en tiempo de ejecución no existe una información genérica dada.

No estoy seguro, pero la siguiente pregunta que me podría ser de interés para usted ...

java parámetros de tipo genéricos y operaciones en esos tipos

¿Qué hay de esto:

public class TestMain {
    public static void main(String[] args) throws Exception {
        Type type = TestMain.class.getMethod("dummy").getGenericReturnType();
        System.out.println("type = " + type);
    }

    public List<Integer> dummy() {return null;}
}

Esto imprime:

type = java.util.List<java.lang.Integer>

El siguiente enfoque es problemático:

> public Class<List<String>> getModelType() {
>   return (Class<List<String>>) new ArrayList<String>().getClass();
> }

por ejemplo. Si desea probar si un objeto decir de tipo

org.eclipse.emf.common.util.BasicEList<String> 

es de tipo

List<String> 

basado en el resultado del enfoque getModelType mencionada (), por ejemplo:

BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
    transferFromModelToUi(getModelType().cast(fromObject));
}

el resultado será falsa mientras que debería ser cierto porque ambos objetos implementan la lista de interfaces (desde getModelType () devuelve un objeto de clase de lista de tipos y no ArrayList).

Aquí es un enfoque que trabajó para mí (un poco engorroso, pero conduce a corregir los resultados en el ejemplo anterior, podría ser trasladado a un inicializador estático):

public Class<List<String>> getModelType() {
    Class<?> arrayListClass = new ArrayList<String>().getClass();
    Class<?>[] interfaces = arrayListClass.getInterfaces();
    int index = 0;
    for (int i = 0; i < interfaces.length; i++) {
        if (interfaces[i].equals(List.class)) {
            index = i;
            break;
        }
    }
    return (Class<List<String>>) interfaces[index];
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top