warning convert cast java spring type-safety unchecked

java - convert - Tipo de seguridad: Unchecked cast



java convert object to hashmap (9)

Bueno, en primer lugar, está desperdiciando memoria con la nueva llamada de creación de HashMap . Su segunda línea ignora por completo la referencia a este hashmap creado, haciéndolo disponible para el recolector de basura. Entonces, no hagas eso, usa:

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

En segundo lugar, el compilador se queja de que se convierte el objeto en un HashMap sin comprobar si se trata de un HashMap . Pero, incluso si fueras a hacer:

if(getApplicationContext().getBean("someMap") instanceof HashMap) { private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap"); }

Probablemente todavía obtendría esta advertencia. El problema es que getBean devuelve Object , por lo que no se sabe cuál es el tipo. Convertirlo a HashMap directamente no causaría el problema con el segundo caso (y quizás no haya una advertencia en el primer caso, no estoy seguro de cuán pedante es el compilador de Java con las advertencias para Java 5). Sin embargo, lo estás convirtiendo a un HashMap<String, String> .

HashMaps son realmente mapas que toman un objeto como una clave y tienen un objeto como un valor, HashMap<Object, Object> si lo desea. Por lo tanto, no hay garantía de que cuando obtenga su bean, pueda representarlo como HashMap<String, String> porque podría tener HashMap<Date, Calendar> porque la representación no genérica que se devuelve puede tener cualquier objeto.

Si el código se compila, y puede ejecutar String value = map.get("thisString"); Sin ningún error, no te preocupes por esta advertencia. Pero si el mapa no es completamente de claves de cadena a valores de cadena, obtendrá una ClassCastException en tiempo de ejecución, ya que los genéricos no pueden bloquear que esto suceda en este caso.

En mi archivo de contexto de aplicación de primavera, tengo algo como:

<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String"> <entry key="some_key" value="some value" /> <entry key="some_key_2" value="some value" /> </util:map>

En la clase java, la implementación se ve como:

private Map<String, String> someMap = new HashMap<String, String>(); someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

En Eclipse, veo una advertencia que dice:

Tipo de seguridad: conversión sin verificar de objeto a HashMap

¿Qué hice mal? ¿Cómo resuelvo el problema?


Como lo indican los mensajes anteriores, la Lista no puede diferenciarse entre un List<Object> y un List<String> o List<Integer> .

He resuelto este mensaje de error para un problema similar:

List<String> strList = (List<String>) someFunction(); String s = strList.get(0);

con lo siguiente:

List<?> strList = (List<?>) someFunction(); String s = (String) strList.get(0);

Explicación: La primera conversión de tipo verifica que el objeto es una Lista sin importar los tipos que se mantienen (ya que no podemos verificar los tipos internos en el nivel de Lista). La segunda conversión ahora es necesaria porque el compilador solo sabe que la Lista contiene algún tipo de objetos. Esto verifica el tipo de cada objeto en la Lista a medida que se accede.


El problema es que una conversión es una verificación de tiempo de ejecución, pero debido al borrado de tipo, en el tiempo de ejecución no hay diferencia entre un HashMap<String,String> y HashMap<Foo,Bar> para cualquier otro Foo y Bar .

Use @SuppressWarnings("unchecked") y mantenga su nariz. Ah, y campaña para genéricos reificados en Java :)


Está recibiendo este mensaje porque getBean devuelve una referencia de Objeto y lo está convirtiendo al tipo correcto. Java 1.5 te da una advertencia. Esa es la naturaleza del uso de Java 1.5 o superior con código que funciona así. La primavera tiene la versión segura.

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");

en su lista de tareas pendientes.


La solución para evitar la advertencia sin marcar:

class MyMap extends HashMap<String, String> {}; someMap = (MyMap)getApplicationContext().getBean("someMap");


Otra solución, si se encuentra lanzando mucho el mismo objeto y no desea @SupressWarnings("unchecked") su código con @SupressWarnings("unchecked") , sería crear un método con la anotación. De esta manera, está centralizando el reparto y, con suerte, reduciendo la posibilidad de error.

@SuppressWarnings("unchecked") public static List<String> getFooStrings(Map<String, List<String>> ctx) { return (List<String>) ctx.get("foos"); }


Si realmente desea deshacerse de las advertencias, una cosa que puede hacer es crear una clase que se extienda desde la clase genérica.

Por ejemplo, si estás tratando de usar

private Map<String, String> someMap = new HashMap<String, String>();

Puede crear una nueva clase como tal

public class StringMap extends HashMap<String, String>() { // Override constructors }

Entonces cuando usas

someMap = (StringMap) getApplicationContext().getBean("someMap");

El compilador SABE cuáles son los tipos (ya no genéricos) y no habrá ninguna advertencia. Puede que esta no siempre sea la solución perfecta, algunos podrían argumentar que este tipo de derrotas son el propósito de las clases genéricas, pero aún estás reutilizando todo el mismo código de la clase genérica, simplemente estás declarando en el momento de la compilación qué tipo quieres usar


Una advertencia es solo eso. Una advertencia. A veces las advertencias son irrelevantes, a veces no lo son. Se utilizan para llamar su atención sobre algo que el compilador piensa que podría ser un problema, pero que no lo es.

En el caso de moldes, siempre va a dar una advertencia en este caso. Si está absolutamente seguro de que un reparto en particular estará a salvo, entonces debería considerar agregar una anotación como esta (no estoy seguro de la sintaxis) justo antes de la línea:

@SuppressWarnings (value="unchecked")


Código debajo de las causas Tipo de seguridad

Map<String, Object> myInput = (Map<String, Object>) myRequest.get();

Solución

Cree un nuevo objeto de mapa sin mencionar los parámetros porque no se verifica el tipo de objeto contenido dentro de la lista.

Paso 1: Crear un nuevo mapa temporal

Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();

Paso 2: instanciar el mapa principal

Map<String, Object> myInput=new HashMap<>(myInputObj.size());

Paso 3: Iterar el mapa temporal y establecer los valores en el mapa principal

for(Map.Entry<?, ?> entry :myInputObj.entrySet()){ myInput.put((String)entry.getKey(),entry.getValue()); }