En plus de nous fournir diverses informations sur l'obtention de cours pendant la période de compilation, Java nous permet également d'obtenir diverses informations sur les classes pendant la période d'exécution à la réflexion. Récupérer les informations de classe par la réflexion et après avoir obtenu des informations de classe, vous pouvez obtenir le contenu connexe suivant:
Cet article introduira également la réflexion Java des aspects ci-dessus. Tous les codes impliqués dans cet article sont reflétés
Tout d'abord, une classe Java est publiée sous forme d'objet de recherche pour la réflexion. Le contenu de la classe est le suivant:
La classe abstraite du public FatherObject implémente Runnable {public void DoSomething () {System.out.println ("Do Things ..."); }} La classe publique ExempleObject étend FatherObject {public int Age = 30; Nom de chaîne publique = "ByHieg"; score entier privé = 60; public void printName () {System.out.println (name); } public int getage () {return âge; } public void Setage (int Age) {this.age = age; } public String getName () {Nom de retour; } public void setName (string name) {this.name = name; } public Integer getScore () {return score; } public void setScore (score entier) {this.score = score; } public exampleObject () {} public exampleObject (nom de chaîne) {} public exampleObject (int age, score entier) {} @Override public void dosomething () {super.doSomething (); } @Override public void run () {System.out.println ("run ..."); }}Objet de classe
Notre application utilisera le point de réflexion de la connaissance. Nous devons vouloir obtenir les informations de la classe lors de l'exécution et effectuer des opérations spécifiques en fonction des informations de la classe. Ensuite, la première chose est d'obtenir les informations de la classe, et un objet de classe est fourni dans le JDK pour enregistrer les informations de la classe. Par conséquent, la première étape de la réflexion consiste à obtenir l'objet de classe. Il existe deux façons d'obtenir des objets de classe dans JDK.
Le premier est que si vous connaissez le nom de la classe lors de l'écriture de code, vous pouvez obtenir directement l'objet de classe de la manière suivante:
Class exampleObjectClass = ExampleObject.class;
Le deuxième type est que si vous ne connaissez pas le nom de la classe lors de l'écriture du code, mais à l'exécution, vous pouvez obtenir une chaîne du nom de classe, et vous pouvez obtenir l'objet de classe de la manière suivante:
Class exampleObjectClass = Class.forName("cn.byhieg.reflectiontutorial.ExampleObject");
Notez que cette méthode doit avoir 2 conditions. Tout d'abord, la chaîne dans Forname doit être entièrement qualifiée, et deuxièmement, la classe de classe doit être inférieure au chemin du chemin de classe, car la méthode lancera une exception de classNotFoundException.
Après avoir obtenu cet objet de classe, vous pouvez obtenir diverses informations sur la classe. Certaines informations ont été mentionnées au début. Ci-dessous, parlons des informations sur la classe qui n'a pas été mentionnée.
Obtenez le nom de la classe
Il existe deux façons d'obtenir le nom de la classe, l'un est getName () et l'autre est getIMPLename (). Le premier obtient un nom entièrement qualifié, et le second obtient un nom de cette classe sans nom de package. Regardez l'exemple suivant: Objet de classe, qui a été obtenu via le code ci-dessus.
String fullClassName = ExampleObjectClass.getName (); String SimpleClassName = ExampleObjectClass.getSimplename (); System.out.println (FullClassName); System.out.println (SimpleClassName); System.out.println (SimpleClassName);
Les résultats sont les suivants:
Cn.ByHieg.ReflectionTutorial.ExampleObjectExampleObject
Obtenez le nom du package de la classe, de la classe parent et de l'interface d'implémentation
Le nom du package et la classe parent de la classe peuvent être obtenus via le code suivant.
// Obtenez des informations de package apackage = exampleObjectClass.getPackage (); System.out.println (apackage); // Obtenez la classe de la classe parent superClass = exampleBjectClass.getsuperclass (); System.out.println (superclass.getSimplename ());
Les résultats sont les suivants:
Package Cn.ByHieg.ReflectionTutorialFatherObject
De toute évidence, l'obtention de la valeur de retour de la classe parent est également un objet de classe. Ensuite, vous pouvez utiliser cet objet pour obtenir des informations sur la classe Parent, telles que juger si la classe parent est une classe abstraite.
System.out.println("父类是不是抽象类" + Modifier.isAbstract(superClass.getModifiers()));
GetModificateurs peut obtenir des modificateurs de classe, obtenez ainsi les modificateurs de classe. Bien sûr, ces getModificateurs peuvent non seulement être appelés objets de classe, mais les objets de méthode peuvent être appelés.
Vous pouvez utiliser la méthode dans la classe java.lang.reflect.modificateur pour vérifier le type du modificateur:
Modifier.isabstract (int modificateurs); modificateur.isfinal (int modificateurs); modificateur.isinterface (modificateurs int); modificateur.isnatif (modificateur int); modificateur.isprivate (int modificateur); modificateur.isprotected (modificateur int); modificateur.ispublic (into modificateur); modificateur. modificateurs); modificateur.issstrict (int modificateurs); modificateur.issynchronisé (modificateurs int); modificateur.istransient (modificateurs int); modificateur.isvolatile (modificateurs int);
De plus, nous pouvons également obtenir l'interface implémentée par la classe parentale
// Obtenez la classe d'interface [] Classes = superClass.getInterfaces (); System.out.println ("interfaces de la classe parent" + classes [0]);Parce que les classes Java peuvent implémenter de nombreuses interfaces, ils utilisent des tableaux, mais lorsque vous les utilisez réellement, vous devez d'abord déterminer la longueur du tableau.
Ci-dessous, nous nous concentrerons sur l'explication du contenu répertorié ci-dessus.
Constructeur
À l'aide de Java Reflection, vous pouvez obtenir un constructeur de classe et créer dynamiquement un objet à l'exécution en fonction du constructeur. Premièrement, Java obtient une instance du constructeur par:
// ConstructorConstructor [] constructeurs = exampleObjectClass.getConstructors (); pour (constructeur constructeur: constructeurs) {System.out.println (constructor.toString ()); }Les résultats sont les suivants:
public cn.byhieg.reflectiontutorial.exampleObject (int, java.lang.integer) public cn.byhieg.reflectiontutorial.exampleobject (java.lang.string) public cn.byhieg.reflectiontutorial.exampleObject ()
Si vous connaissez le type de paramètre du constructeur pour accéder à l'avance, vous pouvez utiliser la méthode suivante pour obtenir le constructeur spécifié, comme suit:
Constructor Constructor = exampleObjectClass.getConstructor (String.Class); System.out.println (Constructor.ToString ());
Le résultat est évidemment:
public cn.byhieg.reflectiontutorial.ExampleObject(java.lang.String)
Un autre constructeur peut également être obtenu de la manière suivante
Constructor Constructor = exampleObjectClass.getConstructor (int.class, Integer.class); System.out.println (Constructor.ToString ());
De plus, si nous ne connaissons pas les paramètres du constructeur et ne pouvons obtenir que tous les objets du constructeur, nous pouvons obtenir les paramètres que chaque constructeur utilise comme suit:
Constructor [] constructeurs = exampleObjectClass.getConstructors (); pour (constructeur constructeur: constructeurs) {class [] ParameterTypes = constructor.getParameterTypes (); System.out.println ("Les paramètres du constructeur sont comme follows============================================================== =============================================================. for (class clz: ParameterTypes) {System.out.println ("ParameterType" + clz.toString ());Les résultats sont les suivants:
The constructor parameters are as follows================================== Parameter type class java.lang.String constructor parameters are as follows========================== Parameter type int parameter type class java.lang.Integer
Ici, on peut voir que la méthode de construction sans paramètre n'imprime pas le résultat. L'objet de classe du type de base et l'objet de classe du type de référence sont différents.
Maintenant, un objet peut être créé dynamiquement basé sur diverses informations du constructeur.
Objet objet = constructor.newinstance (1,100); System.out.println (object.toString ());
Il existe deux conditions pour créer un objet. Le premier est créé via un constructeur de paramètres. La seconde est que l'objet constructeur doit être obtenu via le GetConstructor qui passe dans des informations de paramètres.
La première condition est que pour les objets qui peuvent être créés sans méthodes de construction de paramètres, il n'est pas nécessaire d'obtenir l'objet constructeur. L'objet de classe appelle la méthode NewInstance () et crée directement l'objet.
La deuxième condition est que l'objet constructeur doit être obtenu via le formulaire exampleObjectClass.getConstructor (string.class); Il serait faux d'obtenir le tableau des constructeurs via GetConstructors, puis d'appeler l'objet constructeur spécifié pour créer l'objet dans JDK1.8. Mais JDK1.6 est normal.
variable
À l'aide de Java Reflection, vous pouvez obtenir des informations variables d'une classe lors de l'exécution, et vous pouvez créer un objet et définir sa valeur variable en fonction de la méthode ci-dessus. Premièrement, toutes les variables publiques sont obtenues en suivant la méthode suivante:
Champ [] champs = exampleObjectClass.getFields (); pour (champ de champ: champs) {System.out.println ("La variable est:" + field.toString ()); }Les résultats sont les suivants:
La variable est: public int cn.byHieg.reflectiontutorial.exampleObject.age La variable est: public java.lang.string cn.byhieg.reflectiontutorial.exampleobject.name
De toute évidence, toutes les variables publiques obtenues sont publiques et le score variable privé ci-dessus n'est pas obtenu.
De la même manière que le constructeur est obtenu, nous pouvons spécifier un nom de paramètre, puis obtenir la variable spécifiée:
Field Field = ExampleObjectClass.getField ("Age"); System.out.println ("La variable est:" + field.toString ());Le nom obtenu par la méthode TOSTRING de la variable ci-dessus est trop long. Java fournit la méthode getName à la classe de terrain, qui renvoie le nom de la variable écrite dans la classe. Le code ci-dessus peut être modifié en champ.getName ().
La réflexion fournit non seulement un moyen d'obtenir des variables, mais fournit également un moyen de définir des valeurs variables. En suivant la méthode suivante, vous pouvez modifier la valeur variable d'une classe générée dynamiquement:
ExempleObject Object = ((ExampleObject) Constructor1.NewInstance ("ByHieg")); System.out.println ("L'âge d'origine est" + object.age); field.set (objet, 10); System.out.println ("L'âge après le changement est" + object.age);Les résultats sont les suivants:
L'âge d'origine est de 30 ans et l'âge après le changement est de 10
Selon le code ci-dessus, vous pouvez obtenir un objet de champ nommé Age, puis appeler la méthode définie de l'objet, passer un objet et la valeur à modifier, puis vous pouvez modifier la valeur de l'objet. Notez que cette méthode est non seulement utile pour les variables des membres, mais aussi pour les variables statiques. Bien sûr, s'il s'agit d'une variable statique, il est normal de passer null sans passer l'objet.
méthode
En plus de nous fournir des informations variables de la classe, Java Reflection nous fournit également des informations de méthode. La réflexion nous permet d'obtenir le nom de la méthode, les paramètres de la méthode, le type de retour de méthode et les méthodes d'appel.
Tout d'abord, obtenez la méthode via le code suivant:
// la méthode publique de la méthode de la classe de sortie [] Methods = exampleObjectClass.getMethods (); pour (méthode méthode: méthodes) {System.out.println ("méthode =" + méthode.getName ()); }Code qui ressemble à de l'obtention de variables. GetName est appelé directement ici pour obtenir le nom de la méthode écrit dans la classe. Après avoir écrit cela, vous devez naturellement penser que Java fournit également des méthodes spécifiques basées sur des paramètres.
Méthode méthode = exampleObjectClass.getMethod ("setage", int.class); System.out.println (méthode.getName ());La différence ici est que la méthode GetMethod doit également transmettre des informations sur le type de paramètre, reflétant fournit une méthode pour obtenir des paramètres de méthode et le type de retour. Les exemples d'obtention des paramètres de la méthode sont les suivants:
Méthode méthode = exampleObjectClass.getMethod ("setage", int.class); System.out.println (méthode.getName ()); for (class clz: method.getParameterTypes ()) {System.out.println ("Paramètre de la méthode" + clz.getName ()); }Les résultats sont les suivants:
Le paramètre int de la méthode sexe
Un exemple d'obtention du type de retour de méthode est le suivant:
System.out.println(method.getReturnType().getName());
Les résultats sont les suivants:
void
De plus, la réflexion Java prend en charge les méthodes obtenues via Invoke appels. Les exemples sont les suivants:
method.invoke(exampleObjectClass.newInstance(),1);
Le premier paramètre invoque est cet objet, et le deuxième paramètre est un tableau de longueur variable, et les paramètres de la méthode sont passés. Comme des objets de champ, pour des méthodes statiques, vous pouvez passer des méthodes statiques nulles et appeler.
Variables privées et méthodes privées
La méthode ci-dessus ne peut obtenir que des méthodes et des variables publiques, mais ne peut pas obtenir de méthodes et de variables modifiées non publiques. Java fournit des méthodes supplémentaires pour obtenir des variables et des méthodes non publiques. Autrement dit, les variables et méthodes privées sont obtenues via des méthodes GetDeclaredFields et GetDeclaredMethods. Il prend également en charge l'utilisation de GetDeclaredField (nom de variable) et GetDeclaredMethod (nom de la méthode) pour obtenir le nom de variable spécifié et le nom de la méthode. Cependant, les objets de champ et les objets de méthode obtenus de cette manière ne peuvent pas être directement utilisés. Ces objets doivent être appelés setAccessible (true) pour une utilisation normale. La méthode suivante peut être la même que celle mentionnée ci-dessus.
annotation
Écrivez d'abord une classe contenant des annotations:
@Myannotation (name = "byHieg", value = "Hello World") Classe publique AnnotationObject {@MyAnnotation (name = "Field", Value = "variable") Field de chaîne publique; @Myannotation (name = "méthode", value = "méthode") public void dosomething () {System.out.println ("faire quelque chose"); } public void DOOOGTHING (@myannotation (name = "param", value = "param") String param) {}} @ rétention (retentionPolicy.runtime) public @interface myannotation {public String name (); Valeur de chaîne publique ();}Java nous fournit des informations sur l'obtention d'annotations de classe au moment de l'exécution, et nous pouvons obtenir des annotations de classe, des annotations de méthode, des annotations de paramètres et des annotations variables.
Comme la méthode d'acquisition ci-dessus, Java fournit deux méthodes d'acquisition. L'une consiste à obtenir toutes les annotations et à renvoyer un tableau, et la seconde consiste à spécifier les annotations spécifiées.
Prenons une annotation de classe comme exemple pour expliquer les deux façons d'obtenir.
Classe clz = annotationObject.class; Annotation [] annotations = clz.getAnnotations (); Annotation Annotation = clz.getAnnotation (annotationObject.class);
Ensuite, le traitement ultérieur peut être effectué en fonction de l'annotation obtenue. Voici un exemple de traitement:
pour (annotation Annotation: Annotations) {if (instance d'annotation de myannotation) {Myannotation Myannotation = (myannotation) Annotation; System.out.println ("Name:" + myannotation.name ()); System.out.println ("valeur:" + myannotation.value ()); }}Les annotations de classe ci-dessus sont obtenues en appelant Getannotations à l'aide de l'objet de classe. Les annotations de méthode et les annotations variables sont les mêmes. J'appelle GetDeclaredAnnotations en utilisant respectivement des objets de méthode et des objets de champ pour obtenir des annotations. Je n'ai pas grand-chose à dire. Voir le code de réflexion par exemple
Les annotations des paramètres sont un élément relativement gênant. La méthode d'acquisition est comparée. La première étape consiste d'abord à obtenir l'objet de méthode et à appeler les getParameterannotations. Cependant, cette valeur de retour est un tableau bidimensionnel, car l'objet de méthode a de nombreux paramètres, et chaque paramètre peut avoir de nombreuses annotations. Les exemples sont les suivants:
Méthode Method1 = clz.getMethod ("Dootherthing", String.class); Annotation [] [] annotationInparam = méthode1.getParameTannotations (); Classe [] params = méthode1.getParameterTypes (); int i = 0; for (annotation [] annotations: annotationInParam) {class para = params [i ++]; pour (annotation Annotation: Annotations) {if (instance d'annotation de myannotation) {Myannotation Myannotation = (myannotation) Annotation; System.out.println ("param:" + para.getName ()); System.out.println ("Name:" + myannotation.name ()); System.out.println ("valeur:" + myannotation.value ()); }}}Génériques
Étant donné que les génériques Java sont implémentés par l'effacement, il est difficile d'obtenir directement des informations sur le type de génériques paramétré spécifique, mais nous pouvons obtenir des informations génériques via une forme indirecte en utilisant la réflexion. Par exemple, la classe suivante:
classe publique GenericObject {public list <string> lists; public list <string> getLists () {return lists; } public void setlists (list <string> lists) {this.lists = lists; }}Si une méthode renvoie une classe générique, nous pouvons appeler GetGenericRetTurnType via l'objet de méthode pour getGenericreTurnType pour obtenir le type de paramétrage spécifique de cette classe générique. Regardez le code suivant:
Classe clz = genericObject.class; Méthode méthode = clz.getMethod ("getlists"); Type genericType = méthode.getGenericRetTurype (); if (genericType instance of ParametezedType) {ParametezedType ParametezedType = ((paramétriedType) genericType); Type [] types = ParametezedType.getactualTypeArguments (); pour (type type: types) {classe réelclz = ((classe) type); System.out.println ("Le type de paramétrage est:" + réelClz); }}Les résultats sont les suivants:
参数化类型为: class java.lang.String
Les étapes sont un peu lourdes, donc l'explication suivante est:
J'ai obtenu des informations spécifiques sur les génériques en examinant les résultats.
Si aucune méthode ne renvoie un type générique, nous pouvons également obtenir le type paramétré du type générique par le paramètre de la méthode en tant que classe générique, comme la méthode Setlists dans la classe ci-dessus. Les exemples sont les suivants:
Méthode setMethod = clz.getMethod ("setlists", list.class); Type [] genericParameterTypes = setMethod.getGenericParameterTypes (); for (type genericParameterType: genericParAmEterTypes) {System.out.println ("GenericParAmEterTypes est:" + genericParameterType.getTyPename ()); if (genericParameterType instance of ParametezedType) {ParametezezedType ParameteralizedType = ((paramétriedType) genericArAmEterType); System.out.println ("ParametezedType est:" + ParamecezedType.getTypeName ()); Type Types [] = ParametezedType.getactualTypeArguments (); pour (type type: types) {System.out.println ("Le type paramétré est:" + (((classe) type) .getName ()); }}}Les résultats de l'exécution sont les suivants:
GenericParameterTypes est: java.util.list <java.lang.string> ParametepezedType est: java.util.list <java.lang.string> Le type paramétré est: java.lang.string
Étant donné que les paramètres de la méthode peuvent avoir plus d'un type générique, nous obtenons GENGENERAMETRATYPES pour obtenir un tableau, et nous devons déterminer si chaque élément a un type paramétré. Les étapes suivantes sont similaires à celles ci-dessus, donc je ne dirai pas grand-chose.
Si même les paramètres de méthode ne contiennent pas de classes génériques, alors seul le dernier cas est laissé, via le type de variable, c'est-à-dire que la classe de terrain est utilisée. Les exemples sont les suivants:
Champ champ = clz.getfield ("listes"); Type type = field.getGenericType (); if (type instance de ParametealizedType) {ParametezedType ParameteralizedType = ((ParameteralizedType) Type); Type [] types = ParametezedType.getactualTypeArguments (); pour (type type1: types) {System.out.println ("Type paramétré:" + ((classe) type1) .GetTyPename ()); }}Le principe est le même que ci-dessus, sauf que l'objet type est via field.getGenericType (), donc je ne dirai pas grand-chose sur les opérations restantes.
Il s'agit de l'introduction pour obtenir le type de génériques paramétrés par réflexion.
Tableau
Java Reflection peut fonctionner sur un tableau, y compris la création d'un tableau, l'accès à des valeurs dans un tableau et l'obtention d'un objet de classe d'un tableau.
Parlons-en simplement, créer un tableau et accéder aux valeurs dans le tableau: utiliser la classe de tableau dans la réflexion est celle en dessous du package de réflexion.
// Créez un tableau de type int avec une longueur de 3 int [] intArray = (int []) array.newinstance (int.class, 3); // attribue une valeur au tableau via la réflexion pour (int i = 0; i <intarray.length; i ++) {array.set (intarray, i, i + 2); } // tableau sous forme de réflexion, obtenez la valeur dans le tableau pour (int i = 0; i <intarray.length; i ++) {System.out.println (array.get (intarray, i)); }Ce qui précède consiste à créer un tableau et à accéder aux valeurs du tableau à l'aide de la réflexion.
Pour les objets de classe qui obtiennent un tableau, vous pouvez simplement utiliser Int []. Classe , ou utiliser class.forname, qui est une façon étrange d'écrire:
Classe clz = class.forname ("[i"); System.out.println (clz.getTypeName ());Le résultat est:
int[]
La chaîne de ce forname, [ représente un tableau, je représente un int, le flotteur est f , double est d , etc. Si vous souhaitez obtenir un tableau d'objets ordinaires, utilisez le formulaire suivant:
Class stringClz = Class.forName("[Ljava.lang.String;");
[ Disons que c'est un tableau, le côté droit de L est le nom de classe, et le côté droit du type est un ; ;
Cette façon d'obtenir l'objet de classe du tableau est trop lourde.
Après avoir obtenu l'objet de classe du tableau, certaines de ses méthodes uniques peuvent être appelées, telles que l'appel GetComponentType pour obtenir les informations de type des membres de la table. Par exemple, un tableau int est un type de membre, qui est int.
System.out.println(clz.getComponentType().getTypeName());
Le résultat est int
Résumer
Cette fois, les différentes applications de la réflexion se terminent avec cela, et il peut y avoir des explications de connaissances approfondies à l'avenir. Pour un code spécifique, vous pouvez consulter le code de réflexion
Dans le package SRC, il existe différentes classes et dans la classe de test, il est accès à ces classes.
Ce qui précède est tout le contenu de cet article. J'espère que le contenu de cet article sera d'une aide à l'étude ou au travail de chacun. J'espère également soutenir plus Wulin.com!