Maison  >  Article  >  Java  >  Explication détaillée du rôle de la réflexion Java

Explication détaillée du rôle de la réflexion Java

PHP中文网
PHP中文网original
2017-06-22 14:20:201001parcourir

Le mécanisme de réflexion de Java est l'une des fonctionnalités de Java, et le mécanisme de réflexion est la base de la création d'une technologie de framework. La maîtrise flexible du mécanisme de réflexion Java sera d'une grande aide pour tous ceux qui apprendront la technologie du cadre à l'avenir.

Alors, qu'est-ce que la réflexion en Java ?

Tout le monde sait que pour qu'un programme Java s'exécute, la classe Java doit être chargée par la machine virtuelle Java. Les classes Java ne peuvent pas s'exécuter normalement si elles ne sont pas chargées par la machine virtuelle Java. Désormais, tous les programmes que nous exécutons savent que la classe dont vous avez besoin a été chargée lors de la compilation.

Le mécanisme de réflexion de Java est qu'il ne détermine pas quelle classe est chargée lors de la compilation, mais la charge, la détecte et l'auto-examine uniquement lorsque le programme est en cours d'exécution. Utilisez des classes qui ne sont pas connues au moment de la compilation. Une telle caractéristique est la réflexion.

Alors, que fait la réflexion Java ?

Supposons que nous ayons deux programmeurs. Lorsqu'un programmeur écrit un programme, il doit utiliser la classe écrite par le deuxième programmeur, mais le deuxième programmeur n'a pas terminé le cours. il a écrit. Alors, le code du premier programmeur peut-il être compilé ? Cela ne peut pas être compilé. Grâce au mécanisme de réflexion Java, le premier programmeur peut terminer la compilation de son propre code sans que la classe soit écrite par le deuxième programmeur. Le mécanisme de réflexion de

Java connaît la structure de base de la classe. Cette capacité à détecter la structure de classe de Java est appelée "Auto-révision" des classes Java. Tout le monde a utilisé Jcreator et Eclipse. Lorsque nous construisons un objet, nous appelons les méthodes et propriétés de l’objet. En un clic, l'outil de compilation listera automatiquement toutes les méthodes et propriétés pouvant être utilisées par l'objet au choix de l'utilisateur. Celui-ci utilise le principe de réflexion Java pour détecter et auto-examiner les objets que nous créons.

Class class

Pour utiliser le mécanisme de réflexion Java correctement Vous devez utiliser la classe java.lang.Class. C'est l'origine du mécanisme de réflexion Java. Lorsqu'une classe est chargée, la machine virtuelle Java génère automatiquement un objet Class. Grâce à cet objet Class, nous pouvons obtenir des informations telles que la déclaration et la définition des méthodes, membres et constructeurs correspondant à l'objet Class chargé dans la machine virtuelle.

API de réflexion

Utilisée pour refléter les informations de classe, d'interface ou d'objet dans le virtuel Java actuel machine u

Fonction

—Obtenir les informations de classe d'un objet.
—Obtenir les modificateurs d'accès, les membres, les méthodes, les constructeurs et les informations de superclasse d'une classe.

— Récupère les déclarations de constantes et de méthodes appartenant à une interface .

— Crée une interface dont le nom n'est pas connu tant que le programme n'est pas exécuté.

. — Récupère et définit les membres d'un objet, et même le nom de ce membre n'est connu que pendant l'exécution du programme.


— Méthode pour détecter un objet dont le nom n'est connu que pendant l'exécution

Grâce au mécanisme de réflexion Java, nous pouvons facilement détecter de manière flexible les informations de classe qui ont été chargées dans le virtuel Java machine. Bien entendu, ce type de détection affaiblira les performances de l’opération, donc le moment où recourir à la réflexion dépend des besoins, de la taille de l’entreprise et de l’accumulation d’expérience.

Alors, comment utiliser l'API de réflexion pour connaître les informations d'une classe au moment de l'exécution ?

Exemple de code :

Lors de l'exécution, nous entrons javax.swing.JFrame, puis le résultat d'exécution est le suivant :

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.swing.JOptionPane;
/**
  *本类用于测试反射API,利用用户输入类的全路径,
*找到该类所有的成员方法和成员属性
  */
public class MyTest {
     /**
     *构造方法
     */
    public MyTest(){
       String classInfo=JOptionPane.showInputDialog(null,"输入类全路径");//要求用户输入类的全路径
       try {
           Class cla=Class.forName(classInfo);//根据类的全路径进行类加载,返回该类的Class对象
          
           Method[] method=cla.getDeclaredMethods();//利用得到的Class对象的自审,返回方法对象集合
          
           for(Method me:method){//遍历该类方法的集合
              System.out.println(me.toString());//打印方法信息
           }
          
           System.out.println("********");
          
           Field[] field=cla.getDeclaredFields();//利用得到的Class对象的自审,返回属性对象集合
           for(Field me:field){ //遍历该类属性的集合
              System.out.println(me.toString());//打印属性信息
           }
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
    }
    public static void main(String[] args) {
       new MyTest();
    }
}

public void javax.swing.JFrame.remove(java.awt.Component)

public void javax.swing.JFrame.update(java .awt .Graphiques)

…………

********

public static final int javax.swing.JFrame.EXIT_ON_CLOSE

private int javax.swing.JFrame.defaultCloseOperation

…………

    大家可以发现,类的全路径是在程序运行的时候,由用户输入的。所以虚拟机事先并不知道所要加载类的信息,这就是利用反射机制来对用户输入的类全路径来对类自身的一个自审。从而探知该类所拥有的方法和属性。

通过上面代码,大家可以知道编译工具为什么能够一按点就能列出用户当前对象的属性和方法了。它是先获得用户输入对象的字符串,然后利用反射原理来对这样的类进行自审,从而列出该类的方法和属性。

使用反射机制的步骤:

u导入java.lang.relfect 包

u遵循三个步骤
第一步是获得你想操作的类的 java.lang.Class 对象
第二步是调用诸如 getDeclaredMethods 的方法
第三步使用 反射API 来操作这些信息

获得Class对象的方法

u如果一个类的实例已经得到,你可以使用

       【Class c = 对象名.getClass(); 

      例: TextField t = new TextField();

              Class c = t.getClass();

              Class s = c.getSuperclass();

u如果你在编译期知道类的名字,你可以使用如下的方法

Class c = java.awt.Button.class; 
或者

         Class c = Integer.TYPE;

u如果类名在编译期不知道, 但是在运行期可以获得, 你可以使用下面的方法

          Class c = Class.forName(strg);

   这样获得Class类对象的方法,其实是利用反射API把指定字符串的类加载到内存中,所以也叫类加载器加载方法。这样的话,它会把该类的静态方法和静态属性,以及静态代码全部加载到内存中。但这时候,对象还没有产生。所以为什么静态方法不能访问非静态属性和方法。因为静态方法和属性产生的时机在非静态属性和方法之前。

代码示例:

package  com;
 
public class MyTest {
    public static void main(String[] args) {
       TestOne  one=null;
       try{
       Class  cla=Class.forName("com.TestOne");//进行com.TestOne类加载,返回一个Class对象
       System.out.println("********");
       one=(TestOne)cla.newInstance();//产生这个Class类对象的一个实例,调用该类无参的构造方法,作用等同于new TestOne()
       }catch(Exception e){
           e.printStackTrace();
       }
       TestOne two=new TestOne();
  System.out.println(one.getClass() == two.getClass());//比较两个TestOne对象的Class对象是否是同一个对象,在这里结果是true。说明如果两个对象的类型相同,那么它们会有相同的Class对象
    }
}
 
class TestOne{
    static{
       System.out.println("静态代码块运行");
    }
    TestOne(){
       System.out.println("构造方法");
    }
}

  以上代码过行的结果是:

静态代码块运行

***********

构造方法

构造方法


代码分析:

在进行Class.forName("com.TestOne")的时候,实际上是对com.TestOne进行类加载,这时候,会把静态属性、方法以及静态代码块都加载到内存中。所以这时候会打印出"静态代码块运行"。但这时候,对象却还没有产生。所以"构造方法"这几个字不会打印。当执行cla.newInstance()的时候,就是利用反射机制将Class对象生成一个该类的一个实例。这时候对象就产生了。所以打印"构造方法"。当执行到TestOne two=new TestOne()语句时,又生成了一个对象。但这时候类已经加载完毕,静态的东西已经加载到内存中,而静态代码块只执行一次,所以不用再去加载类,所以只会打印"构造方法",而"静态代码块运行"不会打印。

反射机制不但可以例出该类对象所拥有的方法和属性,还可以获得该类的构造方法及通过构造方法获得实例。也可以动态的调用这个实例的成员方法。

代码示例:

package reflect;
 
import java.lang.reflect.Constructor;
 
 
/**
 *
 * 本类测试反射获得类的构造器对象,
 * 并通过类构造器对象生成该类的实例
 *
 */
public class ConstructorTest {
 
    public static void main(String[] args) {
       try {
           //获得指定字符串类对象
           Class cla=Class.forName("reflect.Tests");
           //设置Class对象数组,用于指定构造方法类型
           Class[] cl=new Class[]{int.class,int.class};
          
           //获得Constructor构造器对象。并指定构造方法类型
           Constructor con=cla.getConstructor(cl);
          
           //给传入参数赋初值
           Object[] x={new Integer(33),new Integer(67)};
          
           //得到实例
           Object obj=con.newInstance(x);
       } catch (Exception e) {
           e.printStackTrace();
       }
    }
 
}
 
class Tests{
    public Tests(int x,int y){
       System.out.println(x+"    "+y);
    }
}

运行的结果是” 33    67。说明我们已经生成了Tests这个类的一个对象。 

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn