Lorsque j’ai commencé à apprendre Java, il était vraiment difficile de comprendre ce qu’était la réflexion.
Certains livres, même les plus classiques, expliquent les choses d'une manière qui rend les gens confus. Peut-être que je suis tout simplement trop stupide.
De plus, on dit en ligne que le mécanisme de réflexion devra être utilisé fréquemment lors de l'apprentissage des cadres à l'avenir, ce qui met toujours les gens un peu mal à l'aise.
J'ai juste accidentellement regardé certains chapitres et vidéos expliquant la réflexion, et je pense pouvoir la comprendre un peu mieux.
Maintenant, j'ai décidé de travailler dur, de lire et d'écrire en même temps, et d'enregistrer ici certains contenus et opérations principaux.
Je pense que, pour une personne stupide comme moi, la meilleure façon d'apprendre est peut-être de répéter
Quand je rencontre quelque chose que je ne comprends pas, je m’arrête et je réapprends. Même si cela me fait perdre beaucoup de temps, cela a aussi un certain effet sur moi.
Ma compréhension est la suivante : la soi-disant réflexion consiste à restaurer les informations complètes de la classe sur la base d'un objet déjà instancié.
Au moins pour moi, je pense que l'avantage que cela m'apporte est que cela me permet de comprendre l'orientation objet de bas en haut.
x_x Ici, je déteste encore ces grosses têtes, elles ont tué toutes mes cellules cérébrales.
Classe de classeSi vous souhaitez compléter la réflexion, vous devez comprendre la classe Class
Exemple 1 : obtenir le nom du package et le nom de la classe via un objetclasse Test {
}
Démo de classe publique {
public static void main (String[] arguments) {
Test t = nouveau Test();
System.out.println(t.getClass());
System.out.println(t.getClass().getName());
}
}
Les résultats de la compilation sont les suivants, faites simplement attention à la façon dont le package est compilé.
La méthode getClass() ici est héritée de la classe Object par défaut.
En Java, la classe Object est la classe parent de toutes les classes. De même, les objets instanciés de toutes les classes sont également des instances de la classe Class.
Cela impliquera donc les concepts de transformation vers le haut et de transformation vers le bas.
Les génériques suivront également ici en raison de l'insécurité des castings descendants.
(Mais ce que je veux dire, c'est que la conception générique ici est très éblouissante ! Bon sang, la conception syntaxique de tout Java est également éblouissante, super dégoûtante !!!)
Exemple 2 : Instanciation de la classe ClassPuisque la classe Class n’a pas de constructeur, la manière d’instancier la classe Class est un peu spéciale. Il existe trois manières :
Objet.getClass()}
Démo de classe publique {
public static void main (String[] arguments) {
//Méthode 1 :
Test t = nouveau Test();
Class<? extends Test> c1 = t.getClass();
System.out.println(c1);
//Méthode 2 :
// Afin d'éviter toute spécificité, la classe Test n'est pas utilisée ici, mais la classe String de la bibliothèque Java est utilisée.
Class<String> c2 = String.class;
System.out.println(c2);
//Méthode 3 :
//la méthode forName() lèvera une exception
Classe<?> c3 = null ;
essayer {
c3 = Classe.forName("Test");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c3);
}
}
Il existe une méthode dans la classe Class appelée newInstance(), qui peut être utilisée pour créer une nouvelle instance de l'objet de classe Class.
Comment le dire ? Le contenu contenu dans l'objet Class est la classe réfléchie. Nous devons construire une nouvelle instance (nouvel objet) de cette classe.
Exemple 3 : Construction d'un objet sans paramètres de la classe Class //Génère une référence à une chaîne
Chaîne s = nulle ;
essayer {
//Downcast l'objet construit vers la classe String
//la méthode newInstance() lèvera une exception
s = (Chaîne) c.newInstance();
} catch (InstanciationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("Longueur de la chaîne : " + s.length());
}
}
Cela construit un nouvel objet sous une forme sans paramètre, tout comme en mode normal
Construire un nouvel objet via le constructeur sans argument revient à
Nous savons qu'en plus des constructeurs sans paramètres, il existe également des constructeurs paramétrés dans une classe.
Alors comment construire des objets sous forme de paramètres en réflexion ? Continuez à lire
Exemple 4 : Objet construit paramétré de la classe Class Démo de classe publique {
//Les méthodes suivantes génèrent trop d'exceptions. Par souci de compacité du code, elles sont ici envoyées directement à la machine virtuelle.
public static void main (String[] args) lève une exception {
Classe<?> c = null ;
essayer {
c = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
char[] ch = {'h','e','l','l','o'};
Chaîne s = nulle ;
//Récupère le constructeur paramétré de l'objet Class. Les paramètres entre parenthèses sont écrits sous la forme : type.class.
Constructeur<?> con = c.getConstructor(char[].class);
//Utilisez cette méthode de construction pour construire un nouvel objet chaîne, le paramètre est un tableau de caractères
s = (String) con.newInstance(ch);
System.out.println("Chaîne construite : " + s);
}
}
Nous utilisons toujours la classe String comme exemple, car la classe String est plus souvent utilisée et est plus facile à comprendre.
Ce qu'il faut noter ici, c'est que le constructeur doit être obtenu à l'aide de la méthode getConstructor().
Quant au type de paramètre, il est : type.class original
Un autre point est que, qu'elle ait des paramètres ou non, la méthode de construction utilisée ici doit exister dans la classe d'origine.
Alors, comment pouvons-nous connaître les informations détaillées telles que la méthode constructeur, la méthode ordinaire, la classe parent héritée, etc. dans la classe d'origine ? Continuez à lire
Obtenez la structure de la classePour obtenir la structure d'une classe par réflexion, nous devons importer un nouveau package java.lang.reflect
Exemple 5 : Obtenir le constructeur d'une classe Démo de classe publique {
//Les méthodes suivantes génèrent trop d'exceptions. Par souci de compacité du code, elles sont ici envoyées directement à la machine virtuelle.
public static void main (String[] args) lève une exception {
Classe<?> c = null ;
essayer {
c = Class.forName("java.lang.Boolean");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//La méthode getConstructors() renvoie ici un tableau Constructor
Constructeur<?>[] cons = c.getConstructors();
//Vous pouvez écrire la méthode d'impression vous-même. Pour plus de commodité, j'utilise Arrays.toString() pour me débrouiller.
System.out.println(Arrays.toString(cons));
}
}
Démo de classe publique {
public static void main (String[] args) lève une exception {
Classe<?> c = null ;
essayer {
c = Class.forName("java.lang.Boolean");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Classe<?>[] in = c.getInterfaces();
System.out.println(Arrays.toString(in));
}
}
Démo de classe publique {
public static void main (String[] args) lève une exception {
Classe<?> c = null ;
essayer {
c = Class.forName("java.lang.Boolean");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Méthode[] m = c.getMethods();
//D'accord, cette fois, je serai miséricordieux et j'écrirai une liste imprimée.
pour (int i = 0; i < m.length; i++) {
System.out.println(m[i]);
}
}
}
classe Personne {
nom de chaîne privé ;
âge int privé ;
}
Démo de classe publique {
public static void main (String[] args) lève une exception {
Classe<?> c = null ;
essayer {
c = Class.forName("Personne");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] f = c.getDeclaredFields();
pour (int i = 0; i < f.length; i++) {
System.out.println(f[i]);
}
}
}
La méthode getDeclaredFielsd() peut obtenir toutes les propriétés et getFields() ne peut obtenir que les propriétés publiques.
Exemple 10 : obtenir la valeur de l'attribut dans cette classe classe Personne {
nom de chaîne publique ;
âge int privé ;
personne publique (nom de chaîne, âge entier) {
this.name = nom ;
this.age = âge;
}
}
Démo de classe publique {
public static void main (String[] args) lève une exception {
Personne p = nouvelle Personne("zhangsan",12);
Classe<?> c = p.getClass();
//Obtenir la valeur de l'attribut public
Champ f1 = c.getField("nom");
//get(p) indique quelle valeur d'objet doit être obtenue
Chaîne str = (Chaîne) f1.get(p);
System.out.println("Nom : " + str);
//Obtenir la valeur de l'attribut privé
Champ f2 = c.getDeclaredField("age");
// l'âge est une propriété privée, alors définissez le contrôle de sécurité sur true
f2.setAccessible(true);
int âge = (int) f2.get(p);
System.out.println("Âge : " + âge);
}
}
Franchement, je n’ai trouvé aucune connaissance en Java qui puisse aveugler mes yeux de titane.
À chaque fois, je dois écrire un tas de syntaxes fastidieuses pour implémenter un gadget, ou bien je dois désespérément appeler l'API et lancer des exceptions désespérément.
Rendre le code qui n'est pas assez compact devenu encombrant
Si j’aime une langue, ses propres caractéristiques doivent m’impressionner avant que je puisse l’utiliser pour créer quelque chose.
Évidemment, Java ne me rend pas heureux. Peut-être que de nombreux programmeurs comme moi sont obligés d'utiliser Java.
Juste pour apaiser mon cœur solitaire, lisez la suite ci-dessous
Exemple d'application de réflexion 11 : modifier les attributs via la réflexion classe Personne {
nom de chaîne privé ;
Personne publique (nom de chaîne) {
this.name = nom ;
}
chaîne publique versChaîne() {
return "Nom : " + this.name ;
}
}
Démo de classe publique {
public static void main (String[] args) lève une exception {
Personne p = new Person("王二狗");
System.out.println(p);
Classe<?> c = p.getClass();
//Définit les propriétés à modifier
Champ f = c.getDeclaredField("nom");
f.setAccessible(true);
//Modifier les propriétés et transmettre l'objet et la valeur à définir
f.set(p, "Zhang Erdan");
System.out.println(p);
}
}
classe Personne {
public void print(int i) {
System.out.println("J'écris des nombres : " + i);
}
public static void say(String str) {
System.out.println("Je dis : " + str);
}
}
Démo de classe publique {
public static void main (String[] args) lève une exception {
Personne p = nouvelle Personne();
Classe<?> c = p.getClass();
// La méthode getMethod() doit transmettre le nom de la méthode et le type de paramètre
Méthode m1 = c.getMethod("print", int.class);
//invoke() signifie appeler et doit transmettre des objets et des paramètres
m1.invoke(p, 10);
Méthode m2 = c.getMethod("say", String.class);
//Le null ici signifie que l'objet n'est pas appelé, c'est-à-dire une méthode statique
m2.invoke(null, "ta sœur");
}
}
Voici une démonstration d'une méthode paramétrée normale et d'une méthode statique
Maintenant que tous les paramètres sont écrits, ceux sans paramètres sont encore plus simples. Il suffit de transmettre directement un objet.
Exemple 13 : Manipulation de tableaux par réflexion Démo de classe publique {
public static void main (String[] args) lève une exception {
int[] arr = {1,2,3,4,5};
Class<?> c = arr.getClass().getComponentType();
System.out.println("Type de tableau : " + c.getName());
int len = Array.getLength(arr);
System.out.println("Longueur du tableau : " + len);
System.out.print("Parcourir le tableau : ");
pour (int je = 0; je < len; i++) {
System.out.print(Array.get(arr, i) + " ");
}
System.out.println();
// modifier le tableau
System.out.println("Le premier élément avant modification : " + Array.get(arr, 0));
Array.set(arr, 0, 3);
System.out.println("Le premier élément modifié : " + Array.get(arr, 0));
}
}
C'est tout pour le moment. Le livre que j'ai lu inclut également l'application de la réflexion en mode usine.
Ce n’est rien de plus que de le remplacer par la méthode forName(). Il n’y a pas grand-chose à dire.
Je suis un débutant en Java. Je déteste la syntaxe et le design dégoûtants de Java.
Tout cela est destiné à Android, pour poser les bases et s'adapter aux travaux futurs.