Je suis nouveau à Java; à travers mes études, j'ai lu que la réflexion est utilisée pour invoquer des classes et des méthodes, et savoir quelles méthodes sont implémentées ou non.
Quand dois-je utiliser la réflexion et quelle est la différence entre utiliser la réflexion et instancier des objets et appeler des méthodes de manière traditionnelle?
java
reflection
Hamzah khammash
la source
la source
Réponses:
La réflexion est beaucoup plus lente que d'appeler simplement des méthodes par leur nom, car elle doit inspecter les métadonnées dans le bytecode au lieu d'utiliser simplement des adresses et des constantes précompilées.
La réflexion est également plus puissante: vous pouvez récupérer la définition d'un membre
protected
oufinal
, supprimer la protection et la manipuler comme si elle avait été déclarée mutable! De toute évidence, cela sape la plupart des garanties que le langage offre normalement à vos programmes et peut être très, très dangereux.Et cela explique à peu près quand l'utiliser. Normalement, non. Si vous voulez appeler une méthode, il suffit de l'appeler. Si vous voulez muter un membre, déclarez-le simplement mutable au lieu d'aller derrière le dos de la compilation.
Une utilisation utile de la réflexion dans le monde réel est lors de l'écriture d'un cadre qui doit interagir avec des classes définies par l'utilisateur, où l'auteur du cadre ne sait pas quels seront les membres (ou même les classes). La réflexion leur permet de traiter n'importe quelle classe sans le savoir à l'avance. Par exemple, je ne pense pas qu'il serait possible d'écrire une bibliothèque complexe orientée aspect sans réflexion.
Autre exemple, JUnit utilisait un peu de réflexion triviale: il énumère toutes les méthodes de votre classe, suppose que toutes celles qui
testXXX
sont appelées sont des méthodes de test et n'exécute que celles-ci. Mais cela peut maintenant être mieux fait avec des annotations à la place, et en fait JUnit 4 est largement passé aux annotations à la place.la source
J'étais comme toi une fois, je ne connaissais pas grand-chose à la réflexion - toujours pas - mais je l'ai utilisée une fois.
J'avais une classe avec deux classes internes, et chaque classe avait beaucoup de méthodes.
J'avais besoin d'invoquer toutes les méthodes de la classe interne et les appeler manuellement aurait été trop de travail.
En utilisant la réflexion, j'ai pu invoquer toutes ces méthodes en seulement 2-3 lignes de code, au lieu du nombre de méthodes elles-mêmes.
la source
Je regrouperais les utilisations de la réflexion en trois groupes:
la source
La réflexion permet à un programme de travailler avec du code qui peut ne pas être présent et de le faire de manière fiable.
Le "code normal" contient des extraits de code
URLConnection c = null
qui, par sa simple présence, font que le chargeur de classe charge la classe URLConnection dans le cadre du chargement de cette classe, lançant une exception ClassNotFound et quittant.La réflexion vous permet de charger des classes en fonction de leurs noms sous forme de chaîne et de les tester pour diverses propriétés (utiles pour plusieurs versions hors de votre contrôle) avant de lancer des classes réelles qui en dépendent. Un exemple typique est le code spécifique à OS X utilisé pour rendre les programmes Java natifs sous OS X, qui ne sont pas présents sur d'autres plates-formes.
la source
Fondamentalement, la réflexion signifie utiliser le code de votre programme comme données.
Par conséquent, l'utilisation de la réflexion peut être une bonne idée lorsque le code de votre programme est une source utile de données. (Mais il y a des compromis, ce n'est donc pas toujours une bonne idée.)
Par exemple, considérons une classe simple:
et vous voulez en générer du XML. Vous pouvez écrire du code pour générer le XML:
Mais c'est beaucoup de code passe-partout, et chaque fois que vous changez la classe, vous devez mettre à jour le code. Vraiment, vous pourriez décrire ce que ce code fait
Il s'agit d'un algorithme, et l'entrée de l'algorithme est la classe: nous avons besoin de son nom, ainsi que des noms, types et valeurs de ses propriétés. C'est là qu'intervient la réflexion: elle vous donne accès à ces informations. Java vous permet d'inspecter les types à l'aide des méthodes de la
Class
classe.Quelques autres cas d'utilisation:
Cependant, une réflexion complète signifie non seulement regarder le code existant (qui en soi est appelé "introspection"), mais aussi modifier ou générer du code. Il y a deux cas d'utilisation importants en Java pour cela: les proxys et les mocks.
Disons que vous avez une interface:
et vous avez une implémentation qui fait quelque chose d'intéressant:
Et en fait, vous avez également une deuxième implémentation:
Maintenant, vous voulez également une sortie de journal; vous voulez simplement un message de journal chaque fois qu'une méthode est appelée. Vous pouvez ajouter explicitement la sortie du journal à chaque méthode, mais ce serait ennuyeux, et vous devriez le faire deux fois; une fois pour chaque implémentation. (Donc encore plus lorsque vous ajoutez plus d'implémentations.)
Au lieu de cela, vous pouvez écrire un proxy:
Encore une fois, cependant, il existe un modèle répétitif qui peut être décrit par un algorithme:
et l'entrée de cet algorithme est la définition de l'interface.
La réflexion vous permet de définir une nouvelle classe à l'aide de cet algorithme. Java vous permet de le faire en utilisant les méthodes de la
java.lang.reflect.Proxy
classe, et il existe des bibliothèques qui vous donnent encore plus de puissance.Quels sont donc les inconvénients de la réflexion?
la source
Reflection peut automatiquement synchroniser certaines parties de votre programme, alors qu'auparavant, vous auriez dû mettre à jour manuellement votre programme pour utiliser les nouvelles interfaces.
la source