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 así:
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 marcar de Objeto a HashMap
¿Qué hice mal? ¿Cómo resuelvo el problema?
java
spring
type-safety
unchecked
DragonBorn
fuente
fuente
Respuestas:
Bueno, antes que nada, estás desperdiciando memoria con la nueva
HashMap
llamada de creación. Su segunda línea ignora por completo la referencia a este hashmap creado, por lo que está disponible para el recolector de basura. Entonces, no hagas eso, usa:En segundo lugar, el compilador se queja de que convierte el objeto en a
HashMap
sin verificar si es aHashMap
. Pero, incluso si tuvieras que hacer:Probablemente aún recibirías esta advertencia. El problema es,
getBean
devuelveObject
, por lo que se desconoce cuál es el tipo. ConvertirloHashMap
directamente no causaría el problema con el segundo caso (y tal vez no haya una advertencia en el primer caso, no estoy seguro de cuán pedante es el compilador de Java con advertencias para Java 5). Sin embargo, lo está convirtiendo en aHashMap<String, String>
.Los HashMaps son realmente mapas que toman un objeto como clave y tienen un objeto como valor,
HashMap<Object, Object>
si se quiere. Por lo tanto, no hay garantía de que cuando obtenga su bean se pueda representar comoHashMap<String, String>
porque podría tenerloHashMap<Date, Calendar>
porque la representación no genérica que se devuelve puede tener algún objeto.Si el código se compila y puede ejecutarlo
String value = map.get("thisString");
sin ningún error, no se preocupe por esta advertencia. Pero si el mapa no es completamente de claves de cadena a valores de cadena, obtendrá unClassCastException
tiempo de ejecución, porque los genéricos no pueden impedir que esto suceda en este caso.fuente
El problema es que un molde es un cheque en tiempo de ejecución - pero debido al tipo de borrado, en tiempo de ejecución en realidad hay ninguna diferencia entre una
HashMap<String,String>
yHashMap<Foo,Bar>
para cualquier otroFoo
yBar
.Usa
@SuppressWarnings("unchecked")
y sostén tu nariz. Ah, y hacer campaña por genéricos reificados en Java :)fuente
Como indican los mensajes anteriores, la Lista no se puede diferenciar entre a
List<Object>
y aList<String>
oList<Integer>
.He resuelto este mensaje de error para un problema similar:
con lo siguiente:
Explicación: La primera conversión de tipo verifica que el objeto es una Lista sin preocuparse por los tipos que contiene (ya que no podemos verificar los tipos internos en el nivel de Lista). Ahora se requiere la segunda conversión porque el compilador solo sabe que la Lista contiene algún tipo de objeto. Esto verifica el tipo de cada objeto en la Lista a medida que se accede.
fuente
Una advertencia es solo eso. Una advertencia. Algunas veces las advertencias son irrelevantes, otras no. Se utilizan para llamar su atención sobre algo que el compilador cree que podría ser un problema, pero que puede no serlo.
En el caso de los moldes, siempre dará una advertencia en este caso. Si está absolutamente seguro de que un reparto en particular será seguro, entonces debería considerar agregar una anotación como esta (no estoy seguro de la sintaxis) justo antes de la línea:
fuente
Está recibiendo este mensaje porque getBean devuelve una referencia de objeto y la está convirtiendo en el 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í. Spring tiene la versión typesafe
en su lista de tareas pendientes.
fuente
Si realmente quiere 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 intentando usar
Puedes crear una nueva clase como tal
Entonces cuando usas
El compilador SÍ sabe cuáles son los tipos (ya no genéricos) y no habrá advertencia. Puede que esta no siempre sea la solución perfecta, algunos podrían argumentar que este tipo de derrotas el propósito de las clases genéricas, pero todavía está reutilizando todo el mismo código de la clase genérica, solo está declarando en el momento de la compilación qué tipo quieres usar
fuente
La solución para evitar la advertencia no verificada:
fuente
Otra solución, si te encuentras lanzando mucho el mismo objeto y no quieres ensuciar tu código
@SupressWarnings("unchecked")
, sería crear un método con la anotación. De esta forma, está centralizando el reparto y, con suerte, reduciendo la posibilidad de error.fuente
El código a continuación causa advertencia de seguridad de tipo
Map<String, Object> myInput = (Map<String, Object>) myRequest.get();
Cree un nuevo objeto de mapa sin mencionar los parámetros porque el tipo de objeto contenido en la lista no está verificado.
Paso 1: crea un nuevo mapa temporal
Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();
Paso 2: crear una instancia del mapa principal
Paso 3: itera el mapa temporal y establece los valores en el mapa principal
fuente
Aquí :
Map<String,String> someMap = (Map<String,String>)getApplicationContext().getBean("someMap");
Utiliza un método heredado que generalmente no queremos usar, ya que devuelve
Object
:El método a favor para obtener (para singleton) / crear (para prototipo) un bean de una fábrica de beans es:
Utilizándolo como:
se compilará pero aún con una advertencia de conversión no verificada, ya que todos los
Map
objetos no son necesariamenteMap<String, String>
objetos.Pero
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
no es suficiente en las clases genéricas de bean, como las colecciones genéricas, ya que eso requiere especificar más de una clase como parámetro: el tipo de colección y sus tipos genéricos.En este tipo de escenario y, en general, un mejor enfoque es no usar
BeanFactory
métodos directamente , sino dejar que el marco inyecte el bean.La declaración de frijol:
La inyección de frijol:
fuente