Tipo de seguridad: lanzamiento sin control
En el archivo de contexto de mi 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 así:
private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
En Eclipse, veo una advertencia que dice:
Seguridad de tipos: conversión sin marcar de Object a HashMap<String,String>
¿Qué salió mal?
El problema es que una conversión es una verificación en tiempo de ejecución, pero debido al borrado de tipos, en tiempo de ejecución en realidad no hay diferencia entre a HashMap<String,String>
y HashMap<Foo,Bar>
para cualquier otro Foo
y Bar
.
Usa @SuppressWarnings("unchecked")
y tapa tu nariz. Ah, y campaña a favor de genéricos cosificados en Java :)
Bueno, primero que nada, estás desperdiciando memoria con la HashMap
llamada de nueva creación. Su segunda línea ignora por completo la referencia a este mapa hash creado, poniéndolo a disposición del 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 usted envía el objeto a HashMap
sin verificar si es un archivo HashMap
. Pero, incluso si tuvieras que hacer:
if(getApplicationContext().getBean("someMap") instanceof HashMap) {
private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}
Probablemente aún recibirás esta advertencia. El problema es que getBean
devuelve Object
, por lo que se desconoce cuál es el tipo. Convertirlo HashMap
directamente no causaría el problema en el segundo caso (y tal vez no habría 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á convirtiendo a HashMap<String, String>
.
Los HashMaps son en realidad mapas que toman un objeto como clave y tienen un objeto como valor, HashMap<Object, Object>
por así decirlo. Por lo tanto, no hay garantía de que cuando obtenga su bean pueda representarse como HashMap<String, String>
porque podría haberlo hecho 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 ejecutarlo String value = map.get("thisString");
sin errores, no se preocupe por esta advertencia. Pero si el mapa no es completamente de claves de cadena a valores de cadena, obtendrá un ClassCastException
en tiempo de ejecución, porque los genéricos no pueden impedir que esto suceda en este caso.