1. Quel est le mécanisme de réflexion ?
En termes simples, le mécanisme de réflexion signifie que le programme peut obtenir ses propres informations lors de son exécution. En Java, tant que le nom de la classe est donné, toutes les informations sur la classe peuvent être obtenues via le mécanisme de réflexion.
2. Où le mécanisme de réflexion est-il utilisé ?
Parfois, nous avons utilisé certaines connaissances, mais nous ne savons pas quelle est la terminologie professionnelle. Lorsque nous venons d'apprendre jdbc, nous avons utilisé une ligne de code, Class.forName("com.mysql.jdbc.Driver.class"). newInstance() ; Mais à cette époque, je savais seulement que cette ligne de code générait une instance d'objet pilote, et je ne connaissais pas sa signification spécifique. Après avoir écouté la leçon sur le mécanisme de réflexion, j'ai réalisé qu'il s'agit d'une réflexion. De nos jours, de nombreux frameworks ouverts utilisent un mécanisme de réflexion. Hibernate et Struts sont tous implémentés à l'aide d'un mécanisme de réflexion.
3. Avantages et inconvénients du mécanisme de réflexion
Pourquoi utiliser le mécanisme de réflexion ? Ne suffit-il pas de créer directement des objets ? Cela implique les notions de dynamique et de statique.
Compilation statique : le type est déterminé au moment de la compilation et l'objet est lié, c'est-à-dire transmis.
Compilation dynamique : déterminez le type et liez l'objet au moment de l'exécution. La compilation dynamique maximise la flexibilité de Java, incarne des applications polymorphes et réduit le couplage entre les classes.
En un mot, l'avantage du mécanisme de réflexion est qu'il peut créer et compiler dynamiquement des objets, ce qui fait preuve d'une grande flexibilité. Surtout dans le développement de J2EE, sa flexibilité est très évidente. Par exemple, pour un logiciel à grande échelle, il est impossible de le concevoir parfaitement en une seule fois. Une fois le programme compilé et publié, lorsqu'on constate que certaines fonctions doivent être mises à jour, on ne peut pas demander à l'utilisateur de désinstaller les précédentes. un puis réinstallez-le. La nouvelle version, si tel est le cas, ce logiciel ne sera certainement pas utilisé par beaucoup de gens. S'il est statique, l'ensemble du programme doit être recompilé une fois pour réaliser la mise à jour de la fonction. S'il utilise le mécanisme de réflexion, il n'a pas besoin d'être désinstallé. Il suffit de le créer et de le compiler dynamiquement au moment de l'exécution pour réaliser la fonction.
Son inconvénient est son impact sur les performances. L'utilisation de la réflexion est essentiellement une opération interprétée dans laquelle nous pouvons indiquer à la JVM ce que nous voulons faire et qui répond à nos exigences. De telles opérations sont toujours plus lentes que la simple exécution directe de la même opération.
4. Quelles informations peuvent être obtenues en utilisant le mécanisme de réflexion ?
En un mot, il peut obtenir toutes les informations qu'il y a dans la classe, mais le prérequis est de connaître le nom de la classe, sinon il n'y aura pas d'autres informations. Tout d'abord, l'objet Class doit être créé à partir du nom complet de la classe. classe entrante.
Class c=Class.forName("className"); Remarque : className doit être le nom complet, c'est-à-dire qu'il doit inclure le nom du package, par exemple, cn.netjava.pojo.UserInfo ;
Object obj=c.newInstance();//Créer une instance de l'objet
OK, une fois que vous avez un objet, tout est facile à gérer. Vous pouvez obtenir toutes les informations que vous souhaitez.
Comment obtenir le constructeur
Constructeur getConstructor(Class[] params)//Obtenir le constructeur public selon les paramètres spécifiés
Constructor[] getConstructors()//Obtenir tous les constructeurs publics
Constructeur getDeclaredConstructor(Class[] params)//Obtenir des constructeurs publics et non publics en fonction des paramètres spécifiés
Constructor[] getDeclaredConstructors()//Obtenir tous les constructeurs publics
Obtenir la méthode de la méthode de classe
Méthode getMethod(String name, Class[] params), récupère la méthode en fonction du nom de la méthode et du type de paramètre
Method[] getMethods()//Obtenir toutes les méthodes publiques
Méthode getDeclaredMethod(String name, Class[] params)//Selon le nom de la méthode et le type de paramètre, obtenez les méthodes publiques et non publiques
Method[] getDeclaredMethods()//Obtenir toutes les méthodes publiques et non publiques
Comment obtenir des attributs dans une classe
Field getField(String name)//Obtenir la variable publique correspondante en fonction du nom de la variable
Field[] getFields()//Obtenir toutes les méthodes publiques de la classe
Field getDeclaredField(String name)//Obtenir des variables publiques et non publiques en fonction du nom de la méthode
Field[] getDeclaredFields()//Obtenir toutes les méthodes publiques et non publiques de la classe
Ce sont ceux qui sont couramment utilisés. Si vous les connaissez, tout le reste sera facile à gérer...
5. Que peut-on faire avec le mécanisme de réflexion ?
Quand j'ai commencé à utiliser jdbc, j'avais envie de vomir lorsque j'écrivais pour accéder à la base de données. Il y avait huit tables, et chaque table avait des opérations d'ajout, de suppression, de modification et de recherche. À cette époque, je ne connaissais pas le concept. mécanisme de réflexion, j'ai donc écrit sur différentes classes DAO dans le tableau, ce qui non seulement accélère le développement, mais rend également le code redondant. Le plus terrible est qu'elles se ressemblent presque, puis les copient et les modifient directement. comme il est facile de commettre diverses erreurs de bas niveau (majuscules et minuscules, une de plus ou une lettre manquante...), une erreur peut vous prendre beaucoup de temps à trouver.
Avec le mécanisme de réflexion Java, tout est facile à gérer. Il vous suffit d'écrire une classe dao avec quatre méthodes, d'ajouter, de supprimer, de modifier et d'interroger, et de transmettre différents objets. classe dao pour chaque table. Le mécanisme de réflexion fera automatiquement le reste pour nous, c'est son avantage. Pour le dire franchement, le mécanisme de réflexion est conçu pour nous aider à faire des choses répétitives et régulières, c'est pourquoi de nombreux logiciels qui génèrent automatiquement du code utilisent désormais le mécanisme de réflexion pour le compléter, à condition que vous saisissiez les paramètres pertinents conformément aux règles. les programmeurs de niveau sont lents. Les plus lents ont été effacés, pourquoi ? Puisqu’il n’est pas nécessaire d’écrire du code, n’importe qui peut le développer, alors pourquoi les programmeurs le font-ils ? Nous n'avons donc qu'une seule issue, c'est de travailler dur et de travailler plus dur, de devenir un programmeur senior, de nous spécialiser dans le développement de logiciels stupides et de laisser les autres programmeurs se mettre de côté et se calmer, haha~
6. Exemple d'utilisation du mécanisme de réflexion pour ajouter et vérifier les données de la base de données
Principe de base : lors de la sauvegarde des données, supprimez toutes les valeurs d'attribut des objets qui doivent être enregistrés, puis rassemblez l'instruction SQL pour la requête et regroupez toutes les données interrogées dans un objet Java.
Règles du jeu : comme le dit le proverbe, il n'y a rien sans règles. Surtout pour les programmes, il ne peut faire des choses qu'avec des règles. D'accord, définissons d'abord les règles.
1) Chaque objet table de la base de données a une classe pojo, et chaque champ de la table correspond à un attribut de la classe pojo. De plus, le nom de la classe pojo est le même que le nom de la table, et le nom de l'attribut et le nom du champ sont les mêmes. La casse n'a pas d'importance, car la base de données n'est généralement pas sensible à la casse.
2) Ajoutez un ensemble standard et obtenez des méthodes pour chaque attribut de la classe pojo.
Avec les règles du jeu, commençons à jouer.
1. Tout d’abord, il existe une table dans la base de données. Supposons que le nom de la base de données soit : blogsystem et qu’un nom de table soit userinfo. Comme le montre l'image :
2. Créez la classe pojo correspondante :
Copiez le code comme suit :
paquet cn.netjava.pojo ;
classe publique UserInfo {
identifiant international privé ;
nom de chaîne privé ;
mot de passe de chaîne privé ;
âge int privé ;
@Outrepasser
chaîne publique versChaîne() {
return "UserInfo [id=" + id + ", name=" + nom + ", pwd=" + pwd + ", age="
+ âge + "]" ;
}
public int getId() {
renvoyer l'identifiant ;
}
public void setId (int id) {
this.id = identifiant;
}
chaîne publique getName() {
renvoyer le nom ;
}
public void setName (nom de la chaîne) {
this.name = nom ;
}
chaîne publique getPwd() {
retourner le mot de passe ;
}
public void setPwd (String pwd) {
this.pwd = pwd;
}
public int getAge() {
âge de retour;
}
public void setAge (int âge) {
this.age = âge;
}
}
2. Écrivez une classe d'usine pour obtenir la connexion à la base de données :
Copiez le code comme suit :
paquet cn.netjava.factory ;
importer java.sql.Connection ;
importer java.sql.DriverManager ;
classe publique Connect2DBFactory {
Connexion statique publique getDBConnection() {
Connexion de connexion = null ;
essayer {
Class.forName("com.mysql.jdbc.Driver");
Chaîne url = "jdbc:mysql://localhost:3306/blogsystem" ;
Chaîne utilisateur = "root" ;
Chaîne de mot de passe = "netjava" ;
conn = DriverManager.getConnection (url, utilisateur, mot de passe);
} attraper (Exception e) {
e.printStackTrace();
}
connexion de retour ;
}
}
3. Le plaisir commence en écrivant la classe dao qui exploite la base de données
Copiez le code comme suit :
paquet cn.netjava.session ;
importer java.lang.reflect.Field ;
importer java.lang.reflect.Method ;
importer java.sql.Connection ;
importer java.sql.PreparedStatement ;
importer java.sql.ResultSet ;
importer java.sql.SQLException ;
importer java.sql.Statement ;
importer java.util.ArrayList ;
importer java.util.List ;
importer cn.netjava.factory.Connect2DBFactory ;
importer cn.netjava.pojo.UserInfo ;
classe publique NetJavaSession {
/**
* Analyser l'instruction SQL qui enregistre l'objet
*
* Objet @param
* : Objet à sauvegarder
* @return : instruction SQL pour enregistrer l'objet
*/
chaîne statique publique getSaveObjectSql (objet objet) {
//Définit une chaîne SQL
String sql = "insérer dans " ;
// Récupère la classe de l'objet
Classe c = object.getClass();
// Récupère toutes les méthodes de l'objet
Method[] méthodes = c.getMethods();
// Récupère toutes les propriétés de l'objet
Field[] champs = c.getFields();
// Récupère le nom de la classe d'objet
Chaîne cName = c.getName();
// Analyse le nom de la table à partir du nom de la classe
String tableName = cName.substring(cName.lastIndexOf(".") + 1,
cName.length());
sql += Nom de la table + "(";
List<String> mList = new ArrayList<String>();
Liste vList = new ArrayList();
pour (Méthode méthode : méthodes) {
String mName = méthode.getName();
if (mName.startsWith("get") && !mName.startsWith("getClass")) {
String fieldName = mName.substring(3, mName.length());
mList.add(fieldName);
System.out.println("Nom du champ----->" + fieldName);
essayer {
Valeur de l'objet = method.invoke(object, null);
System.out.println("La valeur renvoyée par la méthode d'exécution : " + valeur);
if (valeur instance de String) {
vList.add("/"" + valeur + "/"");
System.out.println("Valeur du champ------>" + valeur);
} autre {
vList.add(valeur);
}
} attraper (Exception e) {
e.printStackTrace();
}
}
}
pour (int i = 0; i < mList.size(); i++) {
if (i < mList.size() - 1) {
sql += mList.get(i) + ",";
} autre {
sql += mList.get(i) + ") valeurs(";
}
}
pour (int i = 0; i < vList.size(); i++) {
si (i < vList.size() - 1) {
sql += vList.get(i) + ",";
} autre {
sql += vList.get(i) + ")";
}
}
retourner SQL ;
}
Liste statique publique getDatasFromDB (String tableName, int Id) {
renvoie null ;
}
/**
* Enregistrez l'objet dans la base de données
*
* Objet @param
* : Objet à sauvegarder
* @return : le résultat de l'exécution de la méthode ; 1 : indique le succès, 0 : indique l'échec
*/
public int saveObject (objet objet) {
Connexion con = Connect2DBFactory.getDBConnection();
Chaîne sql = getSaveObjectSql(objet);
essayer {
// Déclaration déclaration = (Déclaration) con.createStatement ();
PreparedStatement psmt = con.prepareStatement(sql);
psmt.executeUpdate();
renvoyer 1 ;
} catch (SQLException e) {
e.printStackTrace();
renvoie 0 ;
}
}
/**
* Récupérez l'objet de la base de données
*
* @param arg0
* : La classe à laquelle appartient l'objet
* identifiant @param
* : identifiant de l'objet
* @return : l'objet à trouver
*/
objet public getObject (String className, int Id) {
// Récupère le nom de la table
String tableName = className.substring(className.lastIndexOf(".") + 1,
className.length());
//Créer un objet Classe basé sur le nom de la classe
Classe c = nulle ;
essayer {
c = Classe.forName(className);
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
// Rassemblez l'instruction SQL de la requête
String sql = "select * from " + tableName + " où Id=" + Id ;
System.out.println("Rechercher l'instruction SQL : " + sql);
// Récupère le lien vers la base de données
Connexion con = Connect2DBFactory.getDBConnection();
//Créer une instance de la classe
Objet obj = nul ;
essayer {
Instruction stm = con.createStatement();
// Récupère le jeu de résultats renvoyé en exécutant l'instruction de recherche
ResultSet set = stm.executeQuery(sql);
// Récupère le tableau de méthodes de l'objet
Method[] méthodes = c.getMethods();
// Parcours du jeu de résultats
while (set.next()) {
obj = c.newInstance();
//Méthodes pour parcourir les objets
pour (Méthode méthode : méthodes) {
String nom_méthode = méthode.getName();
// Si la méthode de l'objet commence par set
if (methodName.startsWith("set")) {
// Récupère le nom du champ dans la table de données en fonction du nom de la méthode
Chaîne nom_colonne = nom_méthode.substring(3,
methodName.length());
// Récupère le type de paramètre de la méthode
Class[] parmts = method.getParameterTypes();
if (parmts[0] == String.class) {
// Si le paramètre est de type String, obtenez la valeur correspondante du jeu de résultats en fonction du nom de la colonne et exécutez la méthode set
method.invoke(obj, set.getString(columnName));
}
if (parmts[0] == int.class) {
method.invoke(obj, set.getInt(columnName));
}
}
}
}
} attraper (Exception e) {
e.printStackTrace();
}
retourner obj ;
}
}
4. Qu’en est-il de l’effet du démarrage du test :
Copiez le code comme suit :
paquet cn.netjava.tester ;
importer cn.netjava.pojo.UserInfo ;
importer cn.netjava.session.NetJavaSession ;
Testeur de classe publique {
public static void main(String args[]) {
//Récupère l'objet NetJavaSession
Session NetJavaSession = new NetJavaSession();
//Créer un objet UserInfo
UserInfo utilisateur = new UserInfo();
//Définit les propriétés de l'objet
utilisateur.setId(6988);
utilisateur.setAge(44);
user.setPwd("pwd");
user.setName("champion");
//Enregistre l'objet dans la base de données
Chaîne sql = session.getSaveObjectSql(user);
System.out.println("Instruction SQL pour enregistrer l'objet : " + sql);
//Rechercher un objet
UserInfo userInfo = (UserInfo) session.getObject(
"cn.netjava.pojo.UserInfo", 6988);
System.out.println("Informations obtenues : " + userInfo);
}
}
5. Résultats imprimés :
7. Résumons
En général, le mécanisme de réflexion Java est une chose très utile. Il peut résoudre beaucoup de problèmes car le mécanisme de réflexion est très flexible, nous n'avons pas besoin de passer trop de temps à écrire des opérations. la méthode consacre plus de temps aux fonctions logiques du projet, ce qui peut réduire considérablement le temps de développement et rendre le code plus lisible. De nombreux frameworks open source existants utilisent des mécanismes de réflexion. Il leur suffit de configurer les fichiers puis d'appeler leurs méthodes selon des règles.