Dans mon fichier de contexte d'application de printemps, j'ai quelque chose comme:
<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>
Dans la classe java, l'implémentation ressemble à:
private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
Dans Eclipse, je vois un avertissement qui dit:
Sécurité du type: conversion non contrôlée de l'objet vers la carte de hachage
Qu'ai-je fait de mal? Comment résoudre le problème?
java
spring
type-safety
unchecked
DragonBorn
la source
la source
Réponses:
Eh bien, tout d'abord, vous perdez de la mémoire avec le nouvel
HashMap
appel à la création. Votre deuxième ligne ignore complètement la référence à cette table de hachage créée, la rendant ensuite disponible pour le garbage collector. Donc, ne faites pas ça, utilisez:Deuxièmement, le compilateur se plaint que vous convertissez l'objet en un
HashMap
sans vérifier s'il s'agit d'unHashMap
. Mais, même si vous deviez faire:Vous obtiendrez probablement toujours cet avertissement. Le problème est,
getBean
renvoieObject
, donc on ne sait pas quel est le type. Le convertirHashMap
directement ne causerait pas de problème avec le second cas (et peut-être qu'il n'y aurait pas d'avertissement dans le premier cas, je ne sais pas à quel point le compilateur Java est pédant avec les avertissements pour Java 5). Cependant, vous le convertissez en aHashMap<String, String>
.Les HashMaps sont vraiment des cartes qui prennent un objet comme clé et ont un objet comme valeur,
HashMap<Object, Object>
si vous voulez. Ainsi, il n'y a aucune garantie que lorsque vous obtenez votre bean, il peut être représenté comme unHashMap<String, String>
car vous pourriez en avoirHashMap<Date, Calendar>
car la représentation non générique renvoyée peut avoir n'importe quel objet.Si le code compile et que vous pouvez l'exécuter
String value = map.get("thisString");
sans erreur, ne vous inquiétez pas de cet avertissement. Mais si la mappe n'est pas complètement composée de clés de chaîne pour les valeurs de chaîne, vous obtiendrez unClassCastException
au moment de l'exécution, car les génériques ne peuvent pas empêcher cela de se produire dans ce cas.la source
Le problème est qu'une conversion est une vérification de l'exécution - mais en raison de l'effacement du type, lors de l'exécution, il n'y a en fait aucune différence entre a
HashMap<String,String>
etHashMap<Foo,Bar>
pour tout autreFoo
etBar
.Utilisez
@SuppressWarnings("unchecked")
et maintenez votre nez. Oh, et faites campagne pour les génériques réifiés en Java :)la source
Comme l'indiquent les messages ci-dessus, la liste ne peut pas être différenciée entre a
List<Object>
et aList<String>
ouList<Integer>
.J'ai résolu ce message d'erreur pour un problème similaire:
avec ce qui suit:
Explication: La première conversion de type vérifie que l'objet est une liste sans se soucier des types contenus (car nous ne pouvons pas vérifier les types internes au niveau de la liste). La deuxième conversion est maintenant requise car le compilateur sait seulement que la liste contient une sorte d'objets. Cela vérifie le type de chaque objet de la liste lors de son accès.
la source
Un avertissement est juste cela. Un avertissement. Parfois, les avertissements ne sont pas pertinents, parfois ils ne le sont pas. Ils sont utilisés pour attirer votre attention sur quelque chose qui, selon le compilateur, pourrait être un problème, mais peut-être pas.
Dans le cas des lancers, cela va toujours donner un avertissement dans ce cas. Si vous êtes absolument certain qu'une distribution particulière sera sûre, alors vous devriez envisager d'ajouter une annotation comme celle-ci (je ne suis pas sûr de la syntaxe) juste avant la ligne:
la source
Vous obtenez ce message car getBean renvoie une référence d'objet et vous le convertissez en type correct. Java 1.5 vous donne un avertissement. C'est la nature de l'utilisation de Java 1.5 ou mieux avec du code qui fonctionne comme ceci. Le printemps a la version typesafe
sur sa liste de tâches.
la source
Si vous voulez vraiment vous débarrasser des avertissements, vous pouvez créer une classe qui s'étend de la classe générique.
Par exemple, si vous essayez d'utiliser
Vous pouvez créer une nouvelle classe comme celle-ci
Ensuite, lorsque vous utilisez
Le compilateur SAIT quels sont les types (qui ne sont plus génériques) et il n'y aura aucun avertissement. Ce n'est peut-être pas toujours la solution parfaite, certains pourraient argumenter que ce type de but contrevient à l'objectif des classes génériques, mais vous réutilisez toujours le même code de la classe générique, vous déclarez simplement au moment de la compilation quel type que vous souhaitez utiliser.
la source
La solution pour éviter l'avertissement non contrôlé:
la source
Une autre solution, si vous vous retrouvez à lancer beaucoup le même objet et que vous ne voulez pas surcharger votre code
@SupressWarnings("unchecked")
, serait de créer une méthode avec l'annotation. De cette façon, vous centralisez la distribution et, espérons-le, réduisez la possibilité d'erreur.la source
Le code ci-dessous provoque la sécurité du type Avertissement
Map<String, Object> myInput = (Map<String, Object>) myRequest.get();
Créez un nouvel objet de carte sans mentionner les paramètres car le type d'objet contenu dans la liste n'est pas vérifié.
Étape 1: créer une nouvelle carte temporaire
Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();
Étape 2: instancier la carte principale
Étape 3: Itérer la carte temporaire et définir les valeurs dans la carte principale
la source
Ici :
Map<String,String> someMap = (Map<String,String>)getApplicationContext().getBean("someMap");
Vous utilisez une méthode héritée que nous ne voulons généralement pas utiliser car elle renvoie
Object
:La méthode à privilégier pour obtenir (pour singleton) / créer (pour prototype) un bean à partir d'une fabrique de bean est:
L'utiliser comme:
va compiler mais toujours avec un avertissement de conversion non contrôlé car tous les
Map
objets ne sont pas nécessairement desMap<String, String>
objets.Mais cela
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
ne suffit pas dans les classes génériques de bean telles que les collections génériques car cela nécessite de spécifier plus d'une classe comme paramètre: le type de collection et son ou ses types génériques.Dans ce type de scénario et en général, une meilleure approche consiste à ne pas utiliser directement
BeanFactory
méthodes mais de laisser le framework injecter le bean.La déclaration du bean:
L'injection de haricot:
la source