2424 votes

Qu'est-ce que la réflexion, et pourquoi est-il utile?

Qu'est-ce que la réflexion, et pourquoi est-il utile?

Je suis particulièrement intéressé par Java, mais je suppose que les principes sont les mêmes dans n'importe quelle langue!

1941voto

Matt Sheppard Points 32256

Le nom de la réflexion est utilisé pour décrire le code qui est en mesure d'inspecter un autre code dans le même système (ou lui-même).

Par exemple, disons que vous avez un objet de type inconnu en Java, et vous souhaitez appeler un "doSomething' méthode si celle-ci existe. Java statique du système de typage n'est pas vraiment conçu pour l'appui de cette à moins que l'objet est conforme à une interface connue, mais l'utilisation de la réflexion, votre code peut ressembler à l'objet et savoir si il a une méthode appelée "doSomething' et ensuite l'appeler si vous le souhaitez.

Donc, pour vous donner un exemple de code de ce en Java (imaginez l'objet en question est toto) :

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);

D'un usage très courant en cas de Java est l'utilisation avec des annotations. JUnit 4, par exemple, utiliser la réflexion pour regarder à travers vos classes pour les méthodes taggés avec l'annotation @Test, et ensuite les appeler lors de l'exécution de l'unité de test.

Il y a quelques bons réflexion exemples pour vous obtenir ont commencé à http://docs.oracle.com/javase/tutorial/reflect/index.html

Et enfin, oui, les concepts sont à peu près similaires dans d'autres statique des types de langues, qui soutien à la réflexion (comme le C#). Dans typées dynamiquement langues, le cas d'utilisation décrit ci-dessus est moins nécessaire (puisque le compilateur va permettre à toute méthode doit être appelée à n'importe quel objet, à défaut lors de l'exécution si elle n'existe pas), mais le deuxième cas de la recherche de méthodes qui sont marqués ou de travailler dans une certaine manière, elle est encore fréquente.

286voto

Liedman Points 3144

"Réflexion" est une langue de la capacité d'inspecter et d'appeler de manière dynamique les classes, méthodes, attributs, etc. au moment de l'exécution. Par exemple, tous les objets en Java a la méthode getClass, qui permet de déterminer sa classe, même si vous ne savez pas au moment de la compilation (comme si vous avez déclaré comme Objet) - cela peut sembler trivial, mais cette réflexion n'est pas par défaut possible en moins de dynamique des langages tels que C++.

Plus avancé utilise vous permet de liste et appeler des méthodes, constructeurs, etc.

La réflexion est importante, car elle permet d'écrire des programmes qui n'ont pas de "savoir" tout ce au moment de la compilation, les rendant plus dynamique, car ils peuvent être attachés ensemble au moment de l'exécution. Le code peut être écrit contre connu des interfaces, mais les classes à utiliser peut être instancié en utilisant la réflexion à partir de fichiers de configuration.

Beaucoup de modernes cadres utilise la réflexion largement pour cette raison.

La plupart des autres langues modernes utilise la réflexion, et des langages de script comme Python peut être dit pour être encore plus étroitement intégrés, puisqu'il correspond à plus naturellement avec le grand modèle de programmation pour les langues.

124voto

Ben Williams Points 936

L'un de mes préférés utilise de réflexion est en dessous de Java méthode de vidage. Il prend l'objet en tant que paramètre et utilise la réflexion Java API imprimer chaque nom de champ et la valeur.

import java.lang.reflect.Array;
import java.lang.reflect.Field;

public static String dump(Object o, int callCount) {
    callCount++;
    StringBuffer tabs = new StringBuffer();
    for (int k = 0; k < callCount; k++) {
        tabs.append("\t");
    }
    StringBuffer buffer = new StringBuffer();
    Class oClass = o.getClass();
    if (oClass.isArray()) {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("[");
        for (int i = 0; i < Array.getLength(o); i++) {
            if (i < 0)
                buffer.append(",");
            Object value = Array.get(o, i);
            if (value.getClass().isPrimitive() ||
                    value.getClass() == java.lang.Long.class ||
                    value.getClass() == java.lang.String.class ||
                    value.getClass() == java.lang.Integer.class ||
                    value.getClass() == java.lang.Boolean.class
                    ) {
                buffer.append(value);
            } else {
                buffer.append(dump(value, callCount));
            }
        }
        buffer.append(tabs.toString());
        buffer.append("]\n");
    } else {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("{\n");
        while (oClass != null) {
            Field[] fields = oClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                buffer.append(tabs.toString());
                fields[i].setAccessible(true);
                buffer.append(fields[i].getName());
                buffer.append("=");
                try {
                    Object value = fields[i].get(o);
                    if (value != null) {
                        if (value.getClass().isPrimitive() ||
                                value.getClass() == java.lang.Long.class ||
                                value.getClass() == java.lang.String.class ||
                                value.getClass() == java.lang.Integer.class ||
                                value.getClass() == java.lang.Boolean.class
                                ) {
                            buffer.append(value);
                        } else {
                            buffer.append(dump(value, callCount));
                        }
                    }
                } catch (IllegalAccessException e) {
                    buffer.append(e.getMessage());
                }
                buffer.append("\n");
            }
            oClass = oClass.getSuperclass();
        }
        buffer.append(tabs.toString());
        buffer.append("}\n");
    }
    return buffer.toString();
}

49voto

toolkit Points 27248

La réflexion est un mécanisme clé pour permettre à une application ou d'un cadre de travail avec un code qui ne pourrait pas avoir encore été écrite!

Prenez l'exemple de votre typique web.xml fichier. Il contient une liste de servlet éléments, qui contiennent imbriquée servlet-class éléments. Le conteneur de servlet sera procédé à la web.xml fichier, et de créer une nouvelle instance de chaque classe de servlet par la réflexion.

Un autre exemple serait la Java API for XML Parsing (JAXP). Où un analyseur XML fournisseur est "branché" par la bien connue des propriétés du système, qui sont utilisés pour construire de nouvelles instances par le biais de la réflexion.

Et enfin, le plus complet exemple est le Printemps qui utilise la réflexion pour créer ses grains, et pour sa forte utilisation de proxys

46voto

Mendelt Points 21583

Pas toutes les langues prend en charge la réflexion, mais les principes sont généralement les mêmes dans les langues qui le prennent en charge.

La réflexion est la capacité à "réfléchir" sur la structure de votre programme. Ou plus concrète. Pour regarder les objets et les classes que vous avez et obtenir par programme de retour d'informations sur les méthodes, les champs, et les interfaces ils mettent en œuvre. Vous pouvez aussi regarder les choses comme les annotations.

Il est utile dans beaucoup de situations. Partout où vous voulez être en mesure de dynamiquement plug dans les classes dans votre code. Beaucoup de objet-relationnel mappeurs utiliser la réflexion pour être en mesure d'instancier des objets de bases de données sans savoir à l'avance quels sont les objets qu'ils vont utiliser. Plug-in architectures est un autre endroit où la réflexion est utile. Être en mesure de charger dynamiquement du code et de déterminer si il y a des types qui mettent en œuvre le droit de l'interface pour l'utiliser comme un plugin est important dans ces situations.

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