Question

Dans mon fichier de contexte d'application printanier, 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>

En 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 disant:

Sécurité du type: transtypage non contrôlé d'objet à tableau de hachage

Qu'est-ce que j'ai mal fait? Comment résoudre le problème?

Était-ce utile?

La solution

Eh bien, tout d’abord, vous gaspillez de la mémoire avec le nouvel appel de création HashMap. Votre deuxième ligne ignore complètement la référence à cette table de hachage créée, la rendant ensuite disponible pour le ramasse-miettes. Alors, ne faites pas ça, utilisez:

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

Deuxièmement, le compilateur se plaint du fait que vous convertissez l'objet en getBean sans vérifier s'il s'agit bien d'un Object. Mais même si vous deviez le faire:

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

Vous aurez probablement toujours cet avertissement. Le problème est que, HashMap<String, String> renvoie HashMap<Object, Object>, le type est inconnu. La convertir directement en HashMap<Date, Calendar> ne causerait pas le 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 des avertissements pour Java 5). Cependant, vous le convertissez en un String value = map.get("thisString");.

Les hashmaps sont en réalité des cartes qui prennent un objet comme clé et qui ont un objet comme valeur, ClassCastException si vous voulez. Ainsi, rien ne garantit que lorsque vous récupérez votre bean, il peut être représenté sous la forme <=> car vous pourriez avoir <=> car la représentation non générique renvoyée peut contenir des objets.

Si le code est compilé et que vous pouvez exécuter <=> sans erreur, ne vous inquiétez pas pour cet avertissement. Mais si la mappe n’est pas complètement composée de clés chaîne en valeurs chaîne, vous obtiendrez un <=> au moment de l’exécution, car les génériques ne peuvent pas empêcher cela de se produire dans ce cas.

Autres conseils

Le problème est qu’une distribution est une vérification au moment de l’exécution - mais en raison de l’effacement du type, au moment de l’exécution, il n’ya aucune différence entre un HashMap<String,String> et un HashMap<Foo,Bar> pour les autres Foo et Bar.

Utilisez @SuppressWarnings("unchecked") et tenez votre nez. Oh, et campagne pour les génériques réifiés en Java:)

Comme l'indiquent les messages ci-dessus, la liste ne peut pas être différenciée entre un List<Object> et un List<String> ou List<Integer>.

J'ai résolu ce message d'erreur pour un problème similaire:

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

avec ce qui suit:

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

Explication: La première conversion de type vérifie que l'objet est une liste sans se soucier des types qu'il contient (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. Ceci vérifie le type de chaque objet de la liste au fur et à mesure de son accès.

Un avertissement, c'est ça. Un avertissement. Parfois, les avertissements ne sont pas pertinents, parfois ils ne le sont pas. Ils sont habitués à attirer votre attention sur quelque chose que le compilateur pourrait poser comme un problème, mais qui pourrait ne pas l'être.

Dans le cas des moulages, il y aura toujours un avertissement dans ce cas. Si vous êtes absolument certain qu'une distribution en particulier sera sans danger, vous devriez envisager d'ajouter une annotation comme celle-ci (je ne suis pas sûr de la syntaxe) juste avant la ligne:

@SuppressWarnings (value="unchecked")

Vous recevez ce message parce que getBean renvoie une référence à un objet et que vous le transmettez au type correct. Java 1.5 vous avertit. C'est la nature d'utiliser Java 1.5 ou mieux avec un code qui fonctionne comme ceci. Spring a la version typesafe

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

sur sa liste de tâches.

Si vous voulez vraiment vous débarrasser des avertissements, vous pouvez créer une classe allant de la classe générique.

Par exemple, si vous essayez d'utiliser

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

Vous pouvez créer une nouvelle classe comme celle-ci

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

Ensuite, lorsque vous utilisez

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

Le compilateur FAIT connaître les types (qui ne sont plus génériques) et il n’y aura pas d’avertissement. Cela n’est peut-être pas toujours la solution idéale, certains diront peut-être que ce type de projet va à l’encontre 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 vous voulez utiliser.

Une autre solution consiste à créer une méthode avec @SupressWarnings ("décoché") si vous lancez souvent le même objet et que vous ne souhaitez pas ajouter du code à votre code. l'annotation. De cette façon, vous centralisez la distribution et, espérons-le, réduisez le risque d'erreur.

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

Le code ci-dessous entraîne une mise en garde sur la sécurité du type

Mappage < Chaîne, objet > myInput = (Map < String, Object >) myRequest.get ();

  

Solution de contournement

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

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

Étape 2: Instanciez la carte principale

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

Étape 3: Itérez la carte temporaire et définissez les valeurs dans la carte principale

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

La solution pour éviter l'avertissement non contrôlé:

class MyMap extends HashMap<String, String> {};
someMap = (MyMap)getApplicationContext().getBean("someMap");
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top