Pour comprendre le principe de réflexion, vous devez d'abord comprendre ce qu'est le type d'informations. Java nous permet d'identifier les informations des objets et des classes lors de l'exécution, et il existe deux façons principales: l'une est la RTTI traditionnelle, qui suppose que nous connaissons déjà toutes les informations de type au moment de la compilation; L'autre est le mécanisme de réflexion, qui nous permet de découvrir et d'utiliser les informations des classes lors de l'exécution .
1. Objet de classe
Pour comprendre comment RTTI fonctionne en Java, vous devez d'abord savoir comment les informations de type sont représentées lors de l'exécution. Cela se fait par des objets de classe, qui contient des informations liées aux classes. Les objets de classe sont utilisés pour créer tous les objets "réguliers". Java utilise des objets de classe pour effectuer RTTI, même si vous effectuez des opérations comme la conversion de type.
Chaque classe générera un objet de classe correspondant, qui est enregistré dans un fichier .class. Toutes les classes sont chargées dynamiquement au JVM lorsqu'ils sont utilisés pour la première fois. Cette classe sera chargée lorsque le programme créera une référence à un membre statique de la classe. Les objets de classe sont chargés uniquement en cas de besoin et l'initialisation statique est effectuée lorsque la classe est chargée.
classe publique testmain {public static void main (string [] args) {System.out.println (xyz.name);}} classe xyz {public static string name = "luoxn28"; static {System.out.println ("xyz static block");}} public xyz () {System.out.println ("xyz construit ");}}Le résultat de la sortie est:
Le chargeur de classe vérifie d'abord si l'objet de classe de cette classe a été chargé. S'il n'a pas été chargé, le chargeur de classe par défaut consultera le fichier .class correspondant en fonction du nom de classe.
Pour utiliser les informations de type à l'exécution, vous devez obtenir une référence à l'objet de classe de l'objet (comme un objet de base). Vous pouvez utiliser la fonction de fonction.Forname ("base") pour y parvenir, ou utiliser Base.class. Notez que c'est intéressant. Lorsque vous utilisez la fonction ".class" pour créer une référence à un objet de classe, l'objet de classe ne sera pas automatiquement initialisé et l'utilisation de ForName () inimisera automatiquement l'objet de classe. Les préparations pour l'utilisation de classes ont généralement les 3 étapes suivantes:
• Chargement: complété par le chargeur de classe, trouver le bytecode correspondant et créer un objet de classe
• Lien: vérifiez le bytecode dans la classe et allouez un espace pour le domaine statique
• Initialisation: si la classe a une superclasse, elle est initialisée et l'initialisateur statique et le bloc d'initialisation statique sont exécutés.
classe publique Base {static int num = 1; static {System.out.println ("base" + num);}} public class Main {public static void main (String [] args) {// Les blocs statiques ne seront pas initialisés class Clazz1 = base.class; System.out.println ("-----"); // classe Cllazz2 = Class.forname ("zzz.base");}} 2. Vérifiez la conversion de type avant
Le compilateur vérifie si la transition à la baisse du type est légale et si elle n'est pas légale, une exception sera lancée. Avant de convertir le type, vous pouvez utiliser l'instance de juger.
classe Base {} classe dérivée étend la base {} public class main {public static void main (string [] args) {base base = new dérivé (); if (instance de baseof dérivé) {// ici vous pouvez convertir down-convert.out.println ("ok");} else {system.out.println ("pas ok");}}}} 3. Réflexion: informations d'exécution
Si vous ne connaissez pas le type exact d'un objet, RTTI peut vous dire, mais il y a une condition préalable: ce type doit être connu au moment de la compilation afin que RTTI puisse être utilisé pour l'identifier. La classe de classe prend en charge la réflexion avec la bibliothèque de classe java.lang.reflect. Cette bibliothèque de classe contient des classes de champ, de méthode et de constructeur. Les objets de ces classes sont créés par le JVM au démarrage pour représenter les membres correspondants dans des classes inconnues. De cette façon, vous pouvez utiliser le contratrice pour créer un nouvel objet, utiliser les méthodes get () et set () pour obtenir et modifier les champs associés à l'objet de champ dans la classe, et utiliser la méthode invoke () pour appeler la méthode associée à l'objet de méthode. De plus, de nombreuses méthodes pratiques telles que getFields (), getMethods () et getConstructors () peuvent également être appelées pour renvoyer un tableau représentant des champs, des méthodes et des objets constructeurs. De cette façon, les informations de l'objet peuvent être complètement déterminées au moment de l'exécution sans rien savoir sur la classe au moment de la compilation.
Il n'y a rien de magique dans le mécanisme de réflexion. Lorsqu'il s'agit d'un objet de type inconnu par la réflexion, le JVM vérifie simplement l'objet pour voir à quelle classe spécifique il appartient. Par conséquent, la classe .Class de cette classe doit être fascinable pour le JVM, soit sur la machine locale, soit à partir du réseau. Ainsi, la vraie différence entre RTTI et la réflexion est uniquement:
• RTTI, le compilateur s'ouvre et vérifie les fichiers.
• Réfléchir, ouvrir et vérifier les fichiers .classe à l'exécution
Public Class Person implémente Serializable {Nom de la chaîne privée; Int privé à l'âge; // Méthode Get / Set} public static void main (String [] args) {Person Person = new Person ("Luoxn28", 23); class Clazz = personne.getClass () Field [] Fields = Clazz.getDeclAredFields (); For Field Field: Fields) {String Key = field.getName (); PropertyDescriptor Descriptor = new PropertyDescriptor (key, Clazz); méthode méthode = descriptor.getReadMethod (); Object Value = Method.invoke (personne); System.out.println (Key + ":" + Value);}} L'appel ci-dessus la fonction Get de la classe via la méthode getReadMethod (), et la méthode getWriteMethod () peut être utilisée pour appeler la méthode définie de la classe. De manière générale, nous n'avons pas besoin d'utiliser des outils de réflexion, mais ils sont plus utiles pour créer du code dynamique. La réflexion est utilisée dans Java pour prendre en charge d'autres fonctionnalités telles que la sérialisation des objets et les javabeans.
4. Agent dynamique
Le mode proxy consiste à fournir des opérations supplémentaires ou différentes, et les objets insérés sont utilisés pour remplacer les objets "réels", qui impliquent la communication avec des objets "réels", de sorte que le proxy agit généralement comme un intermédiaire. Le proxy dynamique de Java est une longueur d'avance sur l'idée du proxy, qui peut créer et proxie et traiter dynamiquement et gérer les appels vers les méthodes de proxy dynamiquement. Tous les appels effectués sur le proxy dynamique sont redirigées vers un processeur d'appel unique, et son travail consiste à révéler le type de l'appel et à déterminer la politique correspondante. Voici un exemple de proxy dynamique:
Classes d'interface et d'implémentation:
Interface interface publique {void dosomething (); void quelque chose quelque chose (String arg);} public class realObject implémente l'interface {public void dosomething () {System.out.println ("Dosomething.");} public void quelque chose (string arg) {System.out.println ("quelque chose delse" + arg);}} Processeur d'objets proxy dynamique:
classe publique DynamicProxyHandler implémente invocationhandler {private objet proxyed; public dynamicproxyhandler (objet proxyed) {this.proxyed = proxyed;} @ overRidepublic invoke (objet proxy, méthode méthode, objet [] args) throw {System.out.println ("Le proxy fonctionne."); Return method.invoke (proxyed, args);}} Classe de test:
classe publique Main {public static void main (string [] args) {realObject real = new RealObject (); Interface proxy = (interface) proxy.newproxyinstance (interface.class.getClassloader (), new class [] {interface.class}, new DynamicProxyHandler (Real)); proxy.dosomething (); proxy.somethingelse ("Luoxn28");}}Le résultat de sortie est le suivant:
Vous pouvez créer un proxy dynamique en appelant la méthode statique proxy proxy.newproxyinstance (). Cette méthode nécessite un chargeur de classe, une liste d'interfaces que vous souhaitez que le proxy implémente (pas une classe ou une classe abstraite) et une classe d'implémentation d'InvocationHandler. Le proxy dynamique peut rediriger tous les appels vers le processeur d'appel, de sorte que le constructeur du processeur d'appel transmet généralement une référence à l'objet "réel", qui transmettra la demande lorsque le processeur d'appel exécute la tâche de médiation.
Ce qui précède est la compréhension approfondie de la réflexion Java qui vous est présentée par l'éditeur. J'espère que cela vous sera utile. Si vous avez des questions, veuillez me laisser un message et l'éditeur vous répondra à temps. Merci beaucoup pour votre soutien au site Web Wulin.com!