Qu'est-ce que la réflexion
"La réflexion permet aux programmes de s'exécuter dans le JVM pour détecter et modifier le comportement de l'exécution." Ce concept est souvent confondu avec l'introspection. Voici les explications de ces deux termes dans Wikipedia:
Exemple d'introspection: L'opérateur d'instance est utilisé pour détecter si un objet appartient à une classe spécifique.
if (obj instance de chien) {chien d = (chien) obj; d.bark ();}Exemple de réflexion: la méthode class.forname () peut obtenir l'objet de classe correspondant via le nom de la classe ou de l'interface (une chaîne ou un nom entièrement qualifié). La méthode FORNAME déclenche l'initialisation de la classe.
// Utiliser la classe de réflexion <?> C = class.forname ("classpath.and.classname"); objet dog = c.newinstance (); méthode m = c.getDeclaredMethod ("Bark", nouvelle classe <?> [0]); M.Invoke (chien);Dans Java, la réflexion est plus proche de l'introspection car vous ne pouvez pas modifier la structure d'un objet. Bien que certaines API puissent être utilisées pour modifier la visibilité des méthodes et des propriétés, elles ne peuvent pas modifier les structures.
Reflet des tableaux
À quoi sert le reflet d'un tableau? Quand avez-vous besoin d'utiliser la réflexion des tableaux? Jetons un coup d'œil au code suivant:
Entier [] nums = {1, 2, 3, 4}; Objet [] objs = nums; // Il peut être automatiquement converti en entier [] en objet [] objet obj = nums; // entier [] est bien sûr un objet int [] ids = {1, 2, 3, 4}; // objet [] objs2 = ids; // L'int [] ne peut pas être converti en objet [] objet obj2 = ids; // int [] est un objetL'exemple ci-dessus montre qu'un type de base de tableau unidimensionnel ne peut être considéré que comme un objet, et non comme un objet [].
int [] [] intArray = {{1, 2}, {3, 4}}; Objet [] oa = intarray; Objet obj = intarray; // Integer [] [] IntegerArray = IntArray; int [] [] pas entier [] [] entier [] [] IntegerArray2 = new Integer [] [] {{1, 2}, {3, 4}}; Objet [] [] OA2 = IntegerArray2; Objet [] oa3 = IntegerArray2; Objet obj2 = IntegerArray2;D'après l'exemple ci-dessus, nous pouvons voir que le tableau à deux chiffres de Java est un tableau de tableaux. Jetons un coup d'œil à l'exemple de refléter un tableau:
package cn.zq.array.reflect; import java.lang.reflect.array; import java.util.arrays; import java.util.random; classe publique ArrayReflect {public static void main (String [] args) {random rand = new random (47); int [] est = new int [10]; for (int i = 0; i <is.length; i ++) {is [i] = rand.nextint (100); } System.out.println (IS); System.out.println (arrays.aslist (IS)); / * Les deux sorties ci-dessus sont des chaînes similaires à "[[i @ 14318bb]", qui ne peut pas afficher le contenu stocké dans le tableau. Bien sûr, nous utilisons la traversée pour produire le contenu dans le tableau * / System.out.println ("- 1. Traversion au tableau par imprime -"); for (int i = 0; i <is.length; i ++) {System.out.print (est [i] + ""); } System.out.println (); System.out.println ("- 2. Traversion au tableau en imprimant -"); Objet obj = est; // convertit le tableau int dimensionnel en OBJECT System.out.println ("obj isArray:" + obj.getClass (). IsArray ()); for (int i = 0; i <array.getLength (obj); i ++) {int num = array.getInt (obj, i); // Vous pouvez également utiliser cette méthode couramment utilisée pour obtenir la valeur de la position d'index correspondante // valeur d'objet = array.get (obj, i); // Si le tableau stocke le type de base, alors le type de wrapper correspondant au type de base System.out.print (num + ""); }}}Sortir:
[I @ 14318bb [[i @ 14318bb] - 1. Imprimez le tableau en traversant le tableau par moyens conventionnels - 58 55 93 61 61 29 68 0 22 7 --2. Imprimez le tableau en traversant le tableau en traversant le tableau en traversant le tableau - obj isarray: true 58 55 93 61 61 29 68 0 22 7
L'exemple ci-dessus crée d'abord un tableau unidimensionnel d'Int, puis remplit au hasard un entier de 0 ~ 100. Ensuite, publiez directement le tableau via la méthode System.out.println () ou utilisez la méthode Arrays. Le tableau est converti en liste puis en sortie, et le passage n'est pas le résultat de sortie que nous attendons. Ensuite, le contenu dans le tableau est sorti dans une méthode de traversée régulière du tableau, puis traitez Int [] comme un objet, et utilisez une réflexion pour traverser son contenu. Class.isArray () peut être utilisé pour déterminer si un objet est un tableau. S'il s'agit d'un tableau, les informations pertinentes du tableau sont obtenues via java.lang.reflect.array, une classe d'outils qui reflète le tableau. Cette classe utilise certaines méthodes GET pour obtenir la longueur du tableau, dont chaque version est utilisée pour obtenir l'index correspondant du tableau unidimensionnel de types de base, une méthode générale pour obtenir la valeur (tableau d'objet, index int), une méthode pour définir la valeur et deux méthodes pour créer des instances de tableau. Grâce à la classe d'outils de réflexion du tableau, il est facile d'utiliser la réflexion du tableau pour écrire du code général sans avoir à juger quel type de base de tableau le tableau donné est.
package cn.zq.array.reflect; import java.lang.reflect.array; classe publique newArrayInstance {public static void main (String [] args) {objet o = array.newinstance (int.class, 20); int [] is = (int []) o; System.out.println ("is.length =" + is.length); Objet o2 = array.newinstance (int.class, 10, 8); int [] [] iss = (int [] []) o2; System.out.println ("Iss.length =" + Iss.length + ", ISS [0] .leght =" + ISS [0] .length); }} is.length = 20 iss.length = 10, iss [0] .leght = 8 Array a passé 2 méthodes pour créer un tableau
Object NewInstance (Class <?> ComponentType, int le long), créez un tableau de longueur spécifiée en fonction de la classe fournie. Si Int.class est fourni comme ci-dessus, la longueur est de 10, ce qui équivaut à New Int [10];
Object NewInstance (classe <?> ComponentType, int ... Dimensions), crée un tableau basé sur la classe et les dimensions fournies. Les dimensions des paramètres variables sont utilisées pour spécifier la longueur de chaque dimension du tableau. Comme dans l'exemple ci-dessus, il équivaut à créer un tableau bidimensionnel de nouveaux int [10] [8], mais il ne peut pas créer un tableau multidimensionnel avec différentes longueurs de chaque dimension. Grâce à la première méthode de création d'un tableau, vous pouvez créer un tableau comme celui-ci. Objet o = array.newinstance (int []. Classe, 20) peut être utilisé pour créer un tableau bidimensionnel, qui est équivalent à l'objet o = new int [20] [];
Bien sûr, il est rare d'utiliser l'exemple ci-dessus pour créer un tableau, mais il est en fait redondant. Pourquoi ne pas créer un tableau directement via nouveau? La réflexion crée un tableau non seulement plus rapide que nouveau, mais aussi le programme écrit n'est pas facile à lire, il n'est donc pas aussi direct que nouveau. En fait, il est vraiment rare de créer des tableaux par la réflexion. Quels types de besoins anormaux existent pour utiliser la réflexion pour créer des tableaux!
Étant donné que certains obstacles ont été rencontrés lors de la sortie d'un tableau de types de base, ce qui suit utilisera la réflexion du tableau pour implémenter une classe d'outils pour atteindre la sortie souhaitée:
package cn.zq.util; Importer java.io.ByteArrayOutputStream; import java.io.printstream; import java.lang.reflect.array; classe publique print {public static void print (objet obj) {print (obj, system.out); } public static void print (objet obj, printStream out) {out.println (getPrintString (obj)); } public static void println () {print (System.out); } public static void println (printStream out) {out.println (); } public static void printnb (objet obj) {printnb (obj, system.out); } public static void printnb (objet obj, printStream out) {out.print (getPrintString (obj)); } public static printStream Format (Format de chaîne, objet ... objets) {return format (System.out, format, objets); } public static printStream Format (printStream out, chaîne Format, objet ... objets) {objet [] handleObjects = new object [objets.Length]; for (int i = 0; i <objets.length; i ++) {objet objet = objets [i]; if (object == null || isPrimitiveWrapper (objet)) {handleObjects [i] = objet; } else {bytearrayoutputStream bos = new bytearrayoutputStream (); PrintStream PS = new PrintStream (BOS); printnb (objet, ps); ps.close (); handleObjects [i] = new String (bos.ToByTearray ()); }} out.format (format, handleObjects); retourner; } / ** * Déterminez si un objet donné est une classe de wrapper du type de base. * @param o Objet d'objet donné * @return Si c'est une classe de wrapper de types primitifs, renvoyez oui, sinon retourne n ° * / privé statique booléen isprimitivewrapper (objet o) {return o instanceof void || o instance de booléen || o Instance de caractère || o instance de byte || o instance de court-circuit || o Instructionof Integer || o instance de long || o Instructionof float || o instance de double; } public static String getPrintString (objet obj) {stringBuilder result = new StringBuilder (); if (obj! = null && obj.getClass (). isArray ()) {result.append ("["); int len = array.getLength (obj); pour (int i = 0; i <len; i ++) {objet valeur = array.get (obj, i); résultat.APPEND (getPrintString (valeur)); if (i! = len - 1) {result.append (","); }} result.append ("]"); } else {result.append (string.valueof (obj)); } return result.toString (); }}La classe d'outils d'impression ci-dessus fournit quelques méthodes statiques pratiques pour la sortie et fournit des versions surchargées. Vous pouvez écrire des versions surchargées en fonction de vos préférences personnelles, en soutenant l'impression des types de base de tableaux unidimensionnels et des tableaux multidimensionnels. Voir les exemples suivants du test d'outil d'impression:
package cn.zq.array.reflect; Importer Static Cn.zq.util.print.print; import java.io.printstream; importer statique cn.zq.util.print. *; classe publique printtest {static class Person {private static int compter; private final int id = compter ++; public String toString () {return getClass (). getImpLename () + id; }} public static void main (String [] args) lève une exception {print ("- imprimer non-chery--"); print (nouvel objet ()); print ("- imprimer un tableau unidimensionnel de types de base--"); int [] est = new int [] {1, 22, 31, 44, 21, 33, 65}; imprimer (IS); Print ("- Imprimez un tableau bidimensionnel de types de base--"); int [] [] iss = new int [] [] {{11, 12, 13, 14}, {21, 22,}, {31, 32, 33}}; imprimer (iss); Print ("- Imprimez un tableau unidimensionnel de types de non-base--"); Personne [] personnes = nouvelle personne [10]; for (int i = 0; i <Persons.Length; i ++) {Persons [i] = new Person (); } print (personnes); imprimer (personnes); Print ("- Imprimez un tableau bidimensionnel de types non primitifs -"); Personne [] [] Persons2 = new Person [] [] {{new Person ()}, {new Person (), new Person ()}, {new Person (), new Person (), new Person (), new Person (),},}; Imprimer (Persons2); print ("- imprimer un tableau vide--"); print (new int [] {}); print ("- Imprimez un tableau avec des valeurs nuls--"); Objet [] objets = nouveau objet [] {new personne (), null, nouvel objet (), new Integer (100)}; print (objets); Print ("- Imprimer un tableau bidimensionnel pour les cas spéciaux--"); Objet [] [] objets2 = nouvel objet [3] []; objets2 [0] = nouvel objet [] {}; objets2 [2] = objets; print (objets2); print ("- Sortir le résultat du tableau unidimensionnel dans le fichier--"); PrintStream out = new PrintStream ("out.c"); essayez {print (iss, out); } enfin {out.close (); } print ("- Format Output--"); format ("% - 6d% s% b% s", 10086, "est", true, iss); / ** * Certaines méthodes d'outils d'impression couramment utilisées sont répertoriées ci-dessus, * Il existe également des méthodes non cotées, veuillez la vérifier vous-même. * /}} Sortir:
- Imprime non-organigramme - java.lang.object@61de33 - Tableau unidimensionnel des types de base - [1, 22, 31, 44, 21, 33, 65] - Tableau bidimensionnel de base - [[11, 12, 13, 14], [21, 22], [31, 32, 33]] - Printe Person1, Person2, Person3, Person4, Person5, Person6, Person7, Person8, Person9] - Print Trembord de type non-base de type non-base - [[Person10], [Person11, Person12], [Person13, Person14, Person15] - Tableau bidimensionnel de l'imprime dans des cas spéciaux - [[], null, [Person16, null, java.lang.object@ca0b6, 100]] - imprime le résultat du tableau unidimensionnel à un fichier - - la sortie du format - 10086 est vrai [[11, 12, 13, 14], [21, 22], [31, 32, 33]]]
Fichier de sortie:
On peut voir que la classe d'outils d'impression a déjà la possibilité d'imprimer des types de base de tableaux unidimensionnels et de tableaux multidimensionnels. De manière générale, la classe d'outils ci-dessus est assez pratique, afin de ne pas écrire manuellement de code chaque fois que vous souhaitez voir le contenu dans le tableau. Ce serait trop gênant. Utilisez simplement la classe d'outils d'impression à l'avenir. Comme c'est pratique.
La classe d'outils ci-dessus fonctionne très bien, mais s'il y a une exigence: donnez un tableau (et peut-être d'autres conteneurs), vous pouvez créer une liste pour moi. Alors que devons-nous faire? En fait, Arrays.aslist n'obtient pas toujours les résultats que nous attendons. Bien que Java5 ajoute des génériques, il a des limites et ne peut pas être aussi général que les modèles C ++. C'est précisément parce qu'il existe des types de base en Java. Même s'il existe un mécanisme d'emballage automatique, il ne peut pas être utilisé avec les génériques. Le type de paramètre doit être d'un certain type, pas un type de base. Voici une solution pour la vôtre:
package cn.zq.util; import java.lang.reflect.array; import java.util.arraylist; import java.util.arrays; Importer Java.util.Enumeration; Importer java.util.iterator; Importer java.util.list; importation java.util.map; COMPECEMENT PUBLIC COLLECTIONUTILS {public static List <?> ASLIST (objet obj) {return conververtolist (Makeiterator (obj)); } public static <T> list <T> conververtolist (iterator <t> iterator) {if (iterator == null) {return null; } List <T> list = new ArrayList <T> (); while (iterator.hasnext ()) {list.add (iterator.next ()); } Retour List; } @SuppressWarnings ({"RawTypes", "Unchecked"}) public static iterator <?> MakeIterator (objet obj) {if (obj instanceof iterator) {return (iterator <?>) Obj; } if (obj == null) {return null; } if (obj instanceof map) {obj = ((map <?,?>) obj) .EntrySet (); } Iterator <?> Iterator = null; if (obj instanceof iteable) {iterator = ((iterable <?>) obj) .iterator (); } else if (obj.getClass (). IsArray ()) {// objet [] objs = (objet []) obj; // ou les tableaux de types primitifs ne peuvent pas être convertis comme cette liste ArrayList = new ArrayList (array.getLength (obj)); for (int i = 0; i <array.getLength (obj); i ++) {list.add (array.get (obj, i)); } iterator = list.iterator (); } else if (obj instanceof énumération) {iterator = new Enunumerationiterator ((énumération) obj); } else {iterator = arrays.aslist (obj) .iterator (); } return iterator; } Classe statique publique Énumerationiterator <T> implémente Iterator <T> {énumération privée <T> Énumération; Public Enunumerationiterator (énumération <T> Énumération) {this.enumeration = énumération; } public boolean hasnext () {return énumération.hasmoreElements (); } public t next () {return énumeration.nextElement (); } public void dissovel () {lance un nouveau non support-operationxception (); }}}Code de test:
package cn.zq.array.reflect; Importer java.util.iterator; Importer java.util.list; Importer cn.zq.array.reflect.printTest.person; import Cn.zq.util.collectionutils; CLASSE PUBLIC COLLECTIONUTULSTEST {public static void main (String [] args) {System.out.println ("--- Type de base Array unidimensionnel--"); int [] nums = {1, 3, 5, 7, 9}; List <?> List = collectionUtils.aslist (nums); System.out.println (liste); System.out.println ("- Not Basic Type Array unidimensionnel--"); Personne [] personnes = new personne [] {new Person (), new Person (), new Person (),}; List <ponv> PersonList = (list <onon>) CollectionUtils.aslist (Persons); System.out.println (PersonList); System.out.println (PersonList); System.out.println ("- Iterator--"); Iterator <ponge> iterator = personneList.iterator (); List <ponv> PersonList2 = (list <onon>) CollectionUtils.aslist (iterator); System.out.println (PersonList2); }}Sortir:
- Array unidimensionnel de type basique - [1, 3, 5, 7, 9] - Array unidimensionnel de type Basic - [Person0, Person1, Person2] --iterator-- [Person0, Person1, Person2]
Dans la bibliothèque de classe Java Container, il peut être divisé en collection, carte et tableau. Étant donné que l'itérateur (et l'énumération précoce de l'interface hérité) est l'interface générale de tous les conteneurs et l'interface de collecte est d'Itérative (l'itérateur de cette interface renverra un itérateur), ces situations sont traitées une par une dans la méthode Makeiterator. Pour les types de cartes, seule la méthode d'entrée () doit être appelée. Pour les classes qui implémentent l'interface itérable (y compris la collection), appelez Iterator () pour obtenir directement l'objet Iterator. Pour les types d'énumération, utilisez l'adaptateur énumération de l'énumération pour l'adaptation. Pour les tableaux, utilisez la réflexion du tableau pour traverser le tableau dans ArrayList et appelez la méthode Arrays.aslist () pour créer une liste pour d'autres types. CollectionUtils fournit également d'autres méthodes à convertir, et vous pouvez ajouter les méthodes dont vous avez besoin selon les besoins.
Résumé: La réflexion du tableau fournit des méthodes plus pratiques et flexibles pour les conceptions où des tableaux peuvent apparaître, afin de ne pas rédiger des déclarations de jugement plus gênantes. Cette flexibilité paie le prix des performances, et il n'est vraiment pas nécessaire d'utiliser la réflexion du tableau lorsque la réflexion du tableau n'est pas du tout nécessaire. Il faut utiliser des réflexions de tableau est différente dans le développement réel. Choisissez si vous devez utiliser les réflexions du tableau en fonction des besoins. La meilleure façon est d'explorer la voie à travers la pratique, d'écrire dans la façon dont vous pensez et de vous améliorer constamment dans la pratique.