初识Java反射机制

最近学到了Java的反射机制,现在对这部分内容做一个总结:

1. Java反射的概念

      在Java运行时动态地获取任意一个类的信息,动态地调用任意对象的方法,这就是Java的反射机制。

2. 反射的优缺点

    优点:对于Java这种静态语言,它使得Java代码更加灵活(灵活性);

    缺点:性能较差(比起直接创建对象进行操作时间上要慢一两个数量级)

3. 实现反射的类

   a. Class类:代表正在运行的类。

 b. Field类:提供类的成员变量信息,就是类的属性。

   c. Method类:提供类的方法信息。

   d. Constructor类:提供类的构造方法信息。

   3.1 Class类介绍

        3.1.1 Class类对象的获取

               获取Class对象的方法有三种,现在逐一对它们进行介绍:

 1 //    第一种方式就是已知的对象,通过对象.getClass()方法来实现
 2     Class class1 = object.getClass();
 3     /*第二种方式就是通过类名.class(类似于调用静态变量,实际不存在class这个变量)
 4     假设存在一个动物类Anaimal*/
 5     Class class2 = Animal.class;
 6     /*第三种方式就是调用Class类的静态方法forName()
 7         此方法使用时会抛出异常(ClassNotFoundException),需要处理
 8         类的全称 = 包名 + 类名*/
 9     try{
10         Class class3 = Class.forName("类的全称");
11     }catch(ClassNotFoundException c){
12         c.printStackTrace();
13     }

       3.1.2 Class类中常用方法

       getFields()方法和getDeclaredFields()方法,返回值是一个Field类型的数组。

 1 Class class1 = ArrayList.class;
 2 Field[] fl = class1.getDeclaredFields();
 3 for(Field f:fl){
 4     System.out.println(f.getName());
 5 }
 6 /*
 7    输出结果为:
 8    serialVersionUID
 9    elementData
10    size
11    MAX_ARRAY_SIZE
12 */
1 Class class1 = ArrayList.class;
2 Field[] f2 = class1.getFields();
3 for(Field l:f2){
4      System.out.println(l.getName());
5 }
6 /*
7   输出结果为空
8 */

 由代码可以看出两个方法都是获取类的属性,但得到的结果不同,那原因是什么呢?我们查询API文档即可得到答案:getFields()方法获得是此 Class 对象所表示的类或接口的所有可访问公共字段,而getDeclaredField()方法获得的是此 Class 对象所表示的类或接口所声明的所有字段(包括私有的公共的受保护的)。由代码结果还可以看出,通过类名.class方式获取类对象,并不能说明该类中就有静态变量class,所以我们只能说类似于调用静态变量的方式去获取。

   getfiled(String name)和getDeclaredField(String name),返回值是一个由name指定的Field对象。调用该方法时可能会抛出NoSuchFieldException异常,需要进行处理。

public static void main(String[] args)throws NoSuchFieldException{
         Class class1 = ArrayList.class;
         Field fl = class1.getDeclaredField("size");
         System.out.println(fl);
}
/*
  输出结果为
  private int java.util.ArrayList.size
*/

public static void main(String[] args)throws NoSuchFieldException{
         Class class1 = ArrayList.class;
         Field fl = class1.getField("size");
         System.out.println(fl);
}

/*
  输出结果为:
  抛出NoSuchFieldException信息
*/

提示:Class类中调用类的构造方法的方法,调用类的方法的方法与调用属性的方法使用相同,大家可自行验证(碍于篇幅限制,就不一一说明了)!

  接下来认识Class类中另一个重要方法,Class.newInstance(),作用是创建此 Class 对象所表示的类的一个新实例,返回值是一个对象。

1 Object obj = Class.newInstance();

  3.2 Field类的介绍

   Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

     3.2.1 Field类的常用方法

     getName()和getType()两个方法,前者返回的是此 Field 对象表示的字段的名称,后者返回的是一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。

1 Class class1 = ArrayList.class;
2 Field fl = class1.getDeclaredField("size");
3 System.out.println("size属性的名字是:"+fl.getName()+"类型是:"+fl.getType());
4 
5 /*
6   输出结果:
7   size属性的名字是:size类型是:int
8 */

  3.3 Method类的介绍

  Method类提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

    3.3.1 Method类常用方法

    invoke(Object obj,Object...args)使用参数args在obj上指派该对象所表示的方法,返回值是一个Object对象,是obj上所指派对象所表示方法的运行结果。

public static void main(String[] args)throws Exception{
         Class class1 = ArrayList.class;
         Object obj = class1.newInstance();
         Method m = class1.getMethod("add",new Class[]{Object.class});
         Object va = m.invoke(obj,new Object[]{5});
         System.out.println(va);
}
/*
  输出结果:
  true
*/

  3.4 Constructor类的介绍

     Constructor类提供关于类的单个构造方法的信息以及对它的访问权限。

      3.4.1 Constructor类常用的方法

             newIntance(object...initargs)方法, 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

1 Class class1 = object.getClass();
2 Constructor con = class1.getConstructor(new Class[]{});
3 Object copy = con.newInstance(new Object[]{});

  到这里,Java反射的一些常用知识,我们就了解,但是想要真正掌握它,离不了多动手练习。为了方便记忆,我将知识进行了梳理,做成了思维导图的形式,方便记忆。

 

   

 

posted @ 2017-04-30 12:58  守明  阅读(254)  评论(0编辑  收藏  举报