Java réflexion (réflexion JAVA) détaillé


La réflexion est le langage de programmation Java des caractéristiques, qui permet d'exécuter des programmes Java sur leur propre inspection, ou "l'auto-examen», et peut attribuer directement les procédures de fonctionnement interne.Par exemple, il peut obtenir un nom de classe Java de chaque membre et l'affichage.

Java, dans l'application pratique de cette capacité peut être utilisée ne sont pas nombreuses, mais dans d'autres langages de programmation de cette fonction n'existe tout simplement pas.Par exemple, Pascal, C ou C + +, il n'existe aucun moyen pour obtenir la définition de fonction dans les informations concernant le programme.

JavaBean est un reflet de l'application pratique, il permet d'outils de visualisation de fonctionnement des composants logiciels.Ces outils sont chargés dynamiquement par la réflexion et obtenir des composants Java (classes) de la propriété.

1. Un exemple simple

Prenons l'exemple simple suivant, nous verrons comment la réflexion de travail.


l'importation java.lang.reflect .*;
public class {DumpMethods
public static void main (String args []) {
try {
Classe c = Class.forName (args [0]);
Méthode m [] = c.getDeclaredMethods ();
for (int i = 0; i m.length; i + +)
System.out.println (m [i] ToString ().);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Instruction est exécutée comme suit:
java DumpMethods java.util.Stack

C'est le résultat obtenu est le suivant:
java.util.Stack.push java.lang.Object public (java.lang.Object)

public java.util.Stack.pop java.lang.Object synchronisée ()

public java.util.Stack.peek java.lang.Object synchronisée ()

java.util.Stack.empty public boolean ()

public int java.util.Stack.search synchronisée (java.lang.Object)

Cette liste le nom de chaque catégorie java.util.Stack méthode et de leur qualification et le type de retour.

Ce programme utilise Class.forName pour charger la classe spécifiée, puis appelez getDeclaredMethods pour obtenir cette classe définit une liste de méthode.java.lang.reflect.Methods est utilisé pour décrire une méthode unique d'une classe d'une classe.


2. Route de réflexion

Pour le reflet de la classe, telles que la méthode, peut être trouvée dans le paquet java.lang.relfect.Lorsque vous utilisez ces classes doivent suivre trois étapes: La première étape est d'obtenir la classe que vous souhaitez utiliser l'objet java.lang.Class.Courir dans le programme Java, avec la classe java.lang.Class pour décrire les classes et interfaces.

Voici les méthodes pour obtenir un objet de classe:
Classe c = Class.forName ("java.lang.String");

Cette déclaration pour obtenir un objet String classe classe.Il est une autre façon, comme la déclaration suivante:
Classe C = int.class;

Ou
Classe C = Integer.TYPE;

Ils reçoivent les types d'informations de base de classe.Visitez l'une des dernière méthode est le type de base du paquet (tel que Integer) dans le domaine pré-défini TYPE.

La deuxième étape consiste à appeler la méthode, comme getDeclaredMethods d'obtenir toutes les méthodes définies dans la liste de classe.

Une fois que vous avez obtenu cette information, la troisième étape peut être réalisée - et d'utiliser les API de réflexion de manipuler l'information, tels que le code suivant:
Classe c = Class.forName ("java.lang.String");

Méthode m [] = c.getDeclaredMethods ();

System.out.println (m [0] ToString ().);

Il permet d'imprimer sous forme de texte String méthode définie dans le premier prototype.

Dans l'exemple ci-dessous, les trois étapes de traitement des demandes spécifiques à utiliser la réflexion pour donner des exemples.

opérateur instanceof analogique

Après obtenir de l'information de classe, le plus souvent la prochaine étape est de résoudre sur l'objet classe de certaines questions fondamentales.Par exemple, la méthode Class.isInstance peut être utilisé pour simuler l'opérateur instanceof:
class A {
}

public class instance1 {
public static void main (String args []) {
try {
cls classe = Class.forName ("A");
boolean b1 = cls.isInstance (new Integer (37));
System.out.println (b1);
boolean b2 = cls.isInstance (Une nouvelle ());
System.out.println (b2);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Dans cet exemple crée une classe d'objets de classe A, puis de vérifier si un objet est une instance de A.Integer (37) n'est pas, mais le nouveau A () est.


3. Pour trouver des méthodes de classe

Trouver une classe définit les méthodes, c'est une utilisation très précieux de réflexion très basique.Le code suivant remplit cet usage:
l'importation java.lang.reflect .*;

public class method1 {
privé int f1 (p Object, int x) {jette NullPointerException
if (p == null)
lancer de nouveaux NullPointerException ();
return x;
}

public static void main (String args []) {
try {
cls classe = Class.forName ("method1");
methlist Méthode [] = cls.getDeclaredMethods ();
for (int i = 0; i methlist.length; i + +) {
m = Méthode methlist [i];
System.out.println ("name =" + m.getName ());
System.out.println ("classe decl =" + m.getDeclaringClass ());
Classe PVEC [] = m.getParameterTypes ();
for (int j = 0; pvec.length j ; j + +)
System.out.println ("param #" + j + "" + PVEC [j]);
Classe evec [] = m.getExceptionTypes ();
for (int j = 0; evec.length j ; j + +)
System.out.println ("exc #" + j + "" + evec [j]);
System.out.println ("type de retour =" + m.getReturnType ());
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Ce programme d'abord obtenir une description de method1 classe, puis appelez getDeclaredMethods pour obtenir une série d'objets Méthode, qui sont définies dans la classe de décrire chacune des méthodes, y compris les méthodes publiques, les méthodes de protection, les méthodes paquet privées et les méthodes.Si vous utilisez le programme pour remplacer getDeclaredMethods GetMethods, vous pouvez obtenir toutes les méthodes héritées.

Méthode pour obtenir une liste d'objets, les paramètres de ces méthodes pour montrer le type de types d'exception et les types de valeur de retour n'est pas difficile.Ces types sont le type de base ou type de classe, peut décrire la classe des objets par l'ordre donné.

La sortie est la suivante:
name = f1

décl class = classe method1

param # 0 java.lang.Object classe

param int # 1

HT # 0 java.lang.NullPointerException classe

type de retour int =

-----
name = principale

décl class = classe method1

param # 0 classe [Ljava.lang.String;

type de retour void =


4. Obtenez de l'information constructeur

Constructeur de classe pour l'utilisation de la ci-dessus pour l'utilisation de méthodes similaires, telles que:
l'importation java.lang.reflect .*;

public class constructor1 {
public constructor1 () {
}

protégées constructor1 (int i, double d) {
}

public static void main (String args []) {
try {
cls classe = Class.forName ("constructor1");
Constructeur ctorlist [] cls.getDeclaredConstructors = ();
for (int i = 0; i ctorlist.length; i + +) {
ct = constructeur ctorlist [i];
System.out.println ("name =" + ct.getName ());
System.out.println ("classe decl =" + ct.getDeclaringClass ());
Classe PVEC [] = ct.getParameterTypes ();
for (int j = 0; pvec.length j ; j + +)
System.out.println ("param #" + j + "" + PVEC [j]);
Classe evec [] = ct.getExceptionTypes ();
for (int j = 0; evec.length j ; j + +)
System.out.println ("exc #" + j + "" + evec [j]);
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Cette affaire n'a pas récupérer le type d'information, c'est parce que le constructeur n'a pas le type de retour.

Le résultat de l'exécution:
name = constructor1

décl class = classe constructor1

-----
name = constructor1

décl class = classe constructor1

param int # 0

param # 1 double


5. Pour le champ de la classe (de domaine)

Trouver une classe définit les champs de données sont également possibles, le code suivant dans le sec cette chose:
l'importation java.lang.reflect .*;

public class {field1
privés double d;
public static final int i = 37;
String s = "test";

public static void main (String args []) {
try {
cls classe = Class.forName ("champ1");
Domaine fieldList [] cls.getDeclaredFields = ();
for (int i = 0; i fieldlist.length; i + +) {
Domaine fld = fieldList [i];
System.out.println ("name =" + fld.getName ());
System.out.println ("classe decl =" + fld.getDeclaringClass ());
System.out.println ("type =" + fld.getType ());
int mod fld.getModifiers = ();
System.out.println ("modificateurs =" + Modifier.toString (mod));
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Cet exemple et est très similaire à l'exemple précédent.Par exemple, utilise quelque chose de nouveau modificateur, il ya aussi une classe de réflexion, les membres du modificateur utilisé pour décrire le domaine, tels que "private int".Ces modificateurs décrits par l'entier lui-même, et l'utilisation Modifier.toString pour revenir à la version "officielle" description de l'ordre de la chaîne (comme «statiques» dans la «finale» avant).La sortie de ce programme est:
name = d

décl class = classe champ1

type = double

modificateurs = privé

-----
name = i

décl class = classe champ1

type = int

modificateurs = public final static

-----
name = s

décl class = classe champ1

type = java.lang.String classe

modificateurs =

La situation et chercher des moyens pour obtenir le champ peut être réalisée que lorsque la classe en l'état actuel de l'information sur le terrain (getDeclaredFields), ou vous pouvez obtenir la classe parente définit les domaines (getFields).


6. Selon le nom de la méthode de la méthode

Texte ici, sans exception, tous les exemples et la façon d'obtenir des informations sur la classe.Nous pouvons également utiliser la réflexion pour faire d'autres choses, telles que la méthode mise en œuvre de spécifier un nom.L'exemple suivant montre ce qui suit:
l'importation java.lang.reflect .*;
public class method2 {
public int add (int a int, b) {
retour a + b;
}
public static void main (String args []) {
try {
cls classe = Class.forName ("method2");
Classe partypes [] = new Class [2];
partypes [0] = Integer.TYPE;
partypes [1] = Integer.TYPE;
Méthode meth = cls.getMethod ("ajouter", partypes);
method2 methobj = new méthode2 ();
Objet arglist [] = new Object [2];
arglist [0] = new Integer (37);
arglist [1] = new Integer (47);
Object = retobj meth.invoke (methobj, arglist);
retval Integer = (Integer) retobj;
System.out.println (retval.intValue ());
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Si quelque part dans la mise en œuvre d'un programme quand il est conscient de la nécessité d'effectuer une méthode, cette méthode est le nom du programme est en cours d'exécution dans le spécifié (par exemple, environnement de développement JavaBean ferait une telle chose), puis le programme ci-dessusmontre comment le faire.

L'exemple ci-dessus, getMethod utilisé pour trouver deux paramètres entiers et ajouter une méthode appelée.Trouvez la méthode et de créer l'objet correspondant méthode, l'instance d'objet dans le droit de l'exécuter.La mise en œuvre de la méthode, la nécessité de fournir une liste de paramètres, qui dans l'exemple ci-dessus est un nombre entier, respectivement, 37 et 47 tours de deux objets Integer.méthode d'exécution est un Integer retour le même objet, qui encapsule la valeur de retour de 84 ans.


7. Pour créer un nouvel objet

Pour le constructeur, vous n'aimez pas la mise en œuvre des méthodes, car cela signifie la mise en œuvre d'un constructeur crée un nouvel objet (pour être exact, le processus de création d'un objet, y compris l'allocation de mémoire et de construire un objet).Ainsi, avec l'exemple le plus similaire de l'exemple précédent comme suit:
l'importation java.lang.reflect .*;

public class constructor2 {
public constructor2 () {
}

public constructor2 (int a int, b) {
System.out.println ("a =" + a + "b =" + b);
}

public static void main (String args []) {
try {
cls classe = Class.forName ("constructor2");
Classe partypes [] = new Class [2];
partypes [0] = Integer.TYPE;
partypes [1] = Integer.TYPE;
ct = constructeur cls.getConstructor (partypes);
Objet arglist [] = new Object [2];
arglist [0] = new Integer (37);
arglist [1] = new Integer (47);
Objet ct.newInstance retobj = (arglist);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Selon le type de paramètre spécifiée pour trouver le constructeur approprié et l'exécuter pour créer une nouvelle instance d'objet.Cette méthode peut être utilisée lors de l'exécution pour créer dynamiquement l'objet, plutôt que de créer des objets lors de la compilation, ce qui est très précieux.


8. Définissez le champ (domaine) la valeur

Il ya aussi une réflexion utile de l'objet est de modifier le champ de la valeur des données.réflexion à partir d'un programme en cours pour trouver des objets par leur nom dans le domaine et le changer, l'exemple suivant pour illustrer ce point:
l'importation java.lang.reflect .*;

public class champ2 {
public double d;

public static void main (String args []) {
try {
cls classe = Class.forName ("champ2");
Domaine fld cls.getField = ("d");
champ2 champ2 f2obj = new ();
System.out.println ("d =" + f2obj.d);
fld.setDouble (f2obj, 12.34);
System.out.println ("d =" + f2obj.d);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Cet exemple, la valeur du champ est modifié par le d 12.34.


9. Utilisation des tableaux

Cet article décrit le reflet de la dernière opération consiste à créer un tableau de l'utilisation.Array dans le langage Java est un type de classe spéciale, une référence de tableau peuvent être affectés de référence de l'objet.Regardez l'exemple ci-dessous pour voir comment le travail de la matrice:
l'importation java.lang.reflect .*;

public class array1 {
public static void main (String args []) {
try {
cls classe = Class.forName ("java.lang.String");
arr Object = Array.newInstance (CLS, 10);
Array.set (arr, 5, "ceci est un test");
String s = (String) Array.get (arr, 5);
System.out.println (s);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Les cas de 10 unités pour créer un tableau String de longueur, pour les 5 premières positions de la chaîne assignée une valeur, et enfin obtenir la chaîne à partir du tableau et l'imprimer.

Le code suivant fournit un exemple plus complexe:
l'importation java.lang.reflect .*;

public class {tableau2
public static void main (String args []) {
dims int [] = new int [] {5, 10, 15};
Objet arr = Array.newInstance (Integer.TYPE, DIMS);
Object = arrobj Array.get (arr, 3);
cls Class = arrobj.getClass () GetComponentType ().
System.out.println (CLS);
arrobj = Array.get (arrobj, 5);
Array.setInt (arrobj, 10, 37);
[][][] Arrcast int = (int arr [][][]);
System.out.println (arrcast [3] [5] [10]);
}
}

Exemple crée un 5 x 10 x 15 tableau de type entier, et dans [3] [5] [10] donne une valeur de 37 éléments.Notez que les tableaux multidimensionnels sont en fait des tableaux de tableaux, par exemple, après la première Array.get, arrobj est un tableau de 10 x 15.Ensuite, récupérez l'un des éléments, à savoir, un tableau de longueur 15, et l'utilisation Array.setInt pour ses 10 premiers éléments de la mission.

Notez que lorsque vous créez le type de tableau est dynamique, au moment de la compilation ne sais pas son type.