61 votes

Pourquoi un double peut-il être ajouté à une liste d'entiers à l'aide de la réflexion?

  public static void main(String args[]) {
        List<Integer> a = new ArrayList<Integer>();
        try {
            a.getClass().getMethod("add", Object.class).invoke(a, new Double(0.55555));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        System.out.println(a.get(0));
    }
 

Pourquoi ce code est-il exécuté sans aucune exception?

94voto

JB Nizet Points 250258

Les génériques sont une chose à la compilation. Au moment de l'exécution, une liste de tableaux classique, sans vérification supplémentaire, est utilisée. Puisque vous contournez les contrôles de sécurité en utilisant la réflexion pour ajouter des éléments à votre liste, rien ne peut empêcher un Double d'être stocké dans votre List<Integer> . Comme si tu le faisais

 List<Integer> list = new ArrayList<Integer>();
List rawList = list;
rawList.add(new Double(2.5));
 

Si vous souhaitez que votre liste implémente des contrôles de type au moment de l'exécution, utilisez

 List<Integer> checkedList = Collections.checkedList(list, Integer.class);
 

35voto

Andrey Chaschev Points 6372

En raison du type d'effacement - il n'y a pas de contrôles d'exécution pour les génériques, lors de la compilation, les paramètres de type sont supprimés: Génériques Java - type effacement - quand et que se passe-t-il .

Vous pourriez être surpris, mais vous n'avez pas besoin d'utiliser la réflexion pour ajouter un Double à un List<Integer> :

 List<Integer> a = new ArrayList<Integer>();
((List)a).add(new Double(0.555));
 

23voto

dasblinkenlight Points 264350

La raison pour cela est de type effacement: le fait que c'est une liste d' Integers est connu pour le compilateur, pas à la JVM.

Une fois que le code est compilé, List<Integer> devient List<Object>, permettant à la fonction de réflexion code complet avec pas d'erreurs.

Notez que votre propre code a un indice sur la raison pour laquelle cela fonctionne:

a.getClass()
    .getMethod("add", Object.class) // <<== Here: Object.class, not Integer.class
    .invoke(a, new Double(0.55555));

Notez également que vous pouvez obtenir le même mauvais résultat par le biais de certains de l'utilisation créative de la coulée, sans réflexion. Tout cela est une conséquence d'une décision de conception pour mettre en œuvre Java génériques avec le type d'effacement.

5voto

Nazgul Points 562

Les génériques ne sont qu'un moment de la compilation, installation de java fournit. Avant de génériques il n'y avait aucun moyen de s'assurer au moment de la compilation que l '"Objet" de l'instance que vous obtenez à partir d'une collection est en fait du type de celui que vous attendez. Nous aurions de jeter l'objet d'un type approprié pour le rendre utilisable dans le code, et cela peut être dangereux, car seulement au moment de l'exécution le temps serait la JVM se plaindre avec une classe de fonte d'exception. il n'y avait rien au moment de la compilation pour nous protéger cette forme.

Les génériques ont résolu ce problème en imposant des vérifications de type dans les collections au moment de la compilation. Mais une autre chose importante à propos des génériques, c'est qu'ils n'existent pas au moment de l'exécution. Si vous décompiler une classe contenant un des types de collection comme la Liste ou sur la Carte et de voir le source java généré à partir d'elle, que vous ne trouverez pas votre collection générique déclaration. Depuis les réflexions code fonctionne au moment de l'exécution et n'a pas le temps de compilation de roulement, de sorte que vous n'obtenez pas une exception. essayez de faire le smae au moment de la compilation avec une normale de vente ou de l'opération d'ajout et vous obtiendrez une erreur de compilation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X