web-dev-qa-db-fra.com

Comment vérifier les types de clé et de valeur si Object instanceof HashMap?

J'ai une méthode qui accepte un objet. Dans un cas d'utilisation, la méthode accepte un HashMap<String, String> et définit chaque valeur sur la propriété du nom de clé correspondant.

public void addHelper(Object object) {
    if (object instanceof HashMap) {
        HashMap<String, String> hashMap = (HashMap<String, String>) object;
        this.foo = hashMap.get("foo");
        this.bar = hashMap.get("bar");
    }
}

Cette classe adhère à une interface particulière, donc l'ajout de setters pour ces propriétés n'est pas une option.

Ma question est, comment puis-je vérifier le type de fonte ici?

HashMap<String, String> hashMap = (HashMap<String, String>) object;

Merci d'avance!

[[# #]] solution [~ # ~]

Grâce à la réponse de @drobert, voici mon code mis à jour:

public void addHelper(Object object) {
    if (object instanceof Map) {
        Map map = (Map) object;
        if (map.containsKey("foo")) this.foo = map.get("foo").toString();
        if (map.containsKey("bar")) this.bar = map.get("bar").toString();
    }
}
15
Shaun Scovil

Tu ne peux pas. En raison de l'effacement des types, la réflexion montrera que vous avez une instance de HashMap, mais les types sont supprimés au moment de l'exécution. En effet, vous avez HashMap <Object, Object>.

Cela dit, vous avez encore quelques options et quelques conseils que je vous suggère de prendre. Parmi eux:

  • Vérifiez s'il s'agit d'une instance de "Map" plutôt que de "HashMap". Cela rendra votre API beaucoup plus flexible car vous ne vous souciez très probablement que d'un accès rapide par clé plutôt que d'une implémentation particulière
  • Profitez de l'API de Java.util.Map qui définit 'containsKey (Object)' et 'get (Object)', de sorte que vous pouvez toujours utiliser mapInst.get ("stringKey") en toute sécurité, même sans avoir à transtyper.
  • Vous ne pouvez pas vous assurer que toutes les valeurs sont des chaînes, mais vous pouvez tirer parti de la méthode toString () de Java.lang.Object et obtenir une chaîne pour chaque valeur malgré tout.

En bref: traitez cela comme n'importe quelle carte, et essayez d'accéder aux clés comme des chaînes même sans le cast, et essayez d'utiliser chaque valeur comme une chaîne en effectuant une vérification nulle puis en appelant .toString () et vous aurez beaucoup plus de sécurité la mise en oeuvre.

20
drobert

Il convient de noter que la routine d'origine est exactement équivalente au codage

public void addHelper(Object object) {
    if (object instanceof HashMap) {
        HashMap hashMap = (HashMap) object;
        this.foo = (String)(hashMap.get("foo"));
        this.bar = (String)(hashMap.get("bar"));
    }
}

Le cast explicite (HashMap) Ne peut pas générer d'erreur, car il est gardé par le instanceof. Les transtypages (String) Fournis implicitement ne génèrent une erreur que si les valeurs renvoyées par HashMap ne sont pas des chaînes (ou des valeurs nulles).

(Par "exactement équivalent à", je veux dire que le même bytecode est produit.)

4
Hot Licks

Vous devez utiliser try-catch, où vous appelez la méthode addHelper(Object). Cela garantira votre type correct de HashMap.

      try{
        addHelper(hashMap);
        }
        catch(ClassCastException ex){
            System.out.println("Is not desired hashmap");
        }
2
Masudul
   try{
    HashMap<String, String> hashMap = (HashMap<String, String>) object;
    this.foo = hashMap.get("foo");
    this.bar = hashMap.get("bar");
    }catch(ClassCastException e){
        System.err.log("Object is not a hashmap");
    }

Maintenant, vous savez que l'objet est du bon type - même une classe abstraite personnalisée ou autre.

0
false_memories