Pregunta

Me preguntaba cuál es el tipo de datos de la variable de plantilla si la devolución se establece en una plantilla. He visto esto en un código en algún lugar, pero no sé de dónde viene echó el valor recuperado de la sesión.

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

El código de este exterior es:

MyClassType type = request.getFromSessionMap("abc");

La línea se encuentra con ClassCastException cuando se lanza al objeto. Pero cuando agrego a ver session.getAttribute ( "ABC"), muestra que el tipo es MyClassType. Cualquier ayuda sería muy apreciada.

Al parecer, este código especial para el uso de la plantilla hace que el retorno de getFromSessionMap un tipo de variable y por lo tanto no hay necesidad de un yeso. Esto funciona en todos los casos pero de pronto fracasó en una parte del código.

¿Fue útil?

Solución

  

Al parecer, este código especial para el uso   plantilla hace el retorno de   getFromSessionMap un tipo de variable y   por lo tanto, no hay necesidad de un molde.

Fundamentalmente, hay tiene que ser a encasillarse en algún lugar entre conseguir el resultado de session.getAttribute(sessionKey) y la asignación a MyClassType. El lenguaje Java (y la JVM) no permitirán algún objeto que no es un ejemplo MyClassType (o un subtipo de la misma) a ser asignado a una variable MyClassType.

No importa la forma de escribir el código, un encasillado tiene que ocurrir . Y puesto que el atributo (aparentemente) no es una MyClassType (o subtipo), que está recibiendo un ClassCastException.

Así que la verdadera pregunta es ¿por qué no conseguir un error de compilación? Y la respuesta es la @SuppressWarnings("unchecked")! Si ha extraído de esa advertencia, se llega a un mensaje de error "conversión de tipo inseguro" para esta línea:

return (T) session.getAttribute(sessionKey);

En verdad, Java no puede hacer una (real) de tipo fundido a un tipo genérico. Y eso es lo que el mensaje / error de advertencia está ahí para señalar. De hecho, una vez que el código ha sido compilado, el código

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

es en realidad no es diferente en el sentido de esto:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

Técnicamente hablando, esto se llama "tipo de borrado".

Entonces, ¿dónde está el tipo de cheques / encasillado ocurriendo realmente? La respuesta está en esta línea:

MyClassType type = request.getFromSessionMap("abc");

A pesar de que usted no ha escrito un encasillado aquí, el código generado por el compilador de Java hace un encasillado antes de asignar el valor a type. Tiene que. Porque por lo que se sabe, la instancia se está asignando podría ser cualquier tipo de objeto.

Otros críticos han sugerido la adición de un argumento de clase a la getFromSessionMap. Por sí mismo esto hace absolutamente nada . Si también reemplaza el cuerpo del método con:

return clazz.cast(session.getAttribute(sessionKey));

que ocasionas el método de hacer realidad un control de tipo real. Pero esto sólo causa ClassCastException a ser lanzado en un lugar diferente. Y la instrucción de asignación se siguen haciendo un tipo de molde oculto !!

Otros consejos

En el ejemplo de la pregunta, el tipo de retorno es T. El tipo será borrado Object como, implícitamente, T extends Object. El reparto real se realiza en el código de bytes del método de llamada (se puede utilizar javap -c ver que).

En general, se debe mantener el número de objetos "de alto nivel" en sesiones lo más pequeño posible. Una de las ventajas de hacer eso, es que ya no hay una necesidad de métodos hacky como estos.

  

Cualquier ayuda se agradece porque mi código se encuentra con ClassCastException.

Si usted está recibiendo un ClassCastException, eso significa que estamos tratando de echar algo en algo que no es, como en el siguiente código:

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

El ClassCastException debe tener un mensaje de detalle esclarecedor, como "java.lang.String no se puede convertir a java.util.Date".

Se utiliza el tipo fundido dentro del cuerpo del método ( '(T) session.getAttribute (SessionKey)' ).

Esto significa que usted dice explícitamente compilador 'Estoy absolutamente seguro de que objeto devuelto ES-A T y listo para manejar error si no es' .

Aquí su suposición sobre tipo de atributo era incorrecta y que tiene un error. Por lo tanto, todo está correcto y el tiempo de ejecución ya se le proporciona el tipo de objeto atributo real que no es IS-A MyClassType.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top