Java基本原理__02_反射 (Reflect)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Coder_Boy_/article/details/83043568

利用反射获取类的相关信息

获取类的相关信息

利用反射API,可以获取类中声明的所有相关信息。

  • 在类中声明的属性
  • 在类中声明的方法
  • 在类中声明的构造器
  • ...

获取属性信息API

Class cls = ...
Field[] flds = cls.getDeclaredFields();

案例:

//动态检查一个类的属性信息
Scanner in = new Scanner(System.in);
String className = in.nextLine();
Class cls = Class.forName(className);
Field[] flds = cls.getDeclaredFields();
for(Field f: flds){
    //f 代表 类中的每个属性信息
    System.out.println(f); 
}

获取方法信息API

//获取类中的方法信息
Method[] methods = 
    cls.getDeclaredMethods();

案例:

//动态加载类
Scanner  in = new Scanner(System.in);
String className = in.nextLine();
//forName() 加载类的时候,如果多次执行
// 方法加载类,实际上只加载一次
Class cls = Class.forName(className);
//动态获取类的方法信息
Method[] methods = 
    cls.getDeclaredMethods();
for(Method m:methods){
    System.out.println(m); 
}

经典案例

模拟实现JUnit3 功能:执行一个类中全部以test为开头方法 注意:类有无参数构造器,方法是无参数的方法。

分析:因为需要运行期间动态分析类的相关信息,必须使用反射API实现!

思路:

  1. 动态加载类
  2. 找到全部方法信息
  3. 遍历全部的方法信息,找到以test为开头的方法。
  4. 执行无参数的test方法。

代码:

//找到一个类中以test为开头方法
Scanner in = new Scanner(System.in);
String className = in.nextLine();
Class cls = Class.forName(className);
Method[] methods =
    cls.getDeclaredMethods();
Object obj = cls.newInstance();
for(Method m:methods){
    //getName() 获取方法信息中的方法名
    String name = m.getName();
    if(name.startsWith("test")){
        //m 是以test为开头方法
        System.out.println(m); 
        //num 代表一个方法的参数个数
        int num = 
            m.getParameterTypes().length;
        if(num==0){
            //执行以test为开头的方法
            Object val=m.invoke(obj);
            System.out.println(val); 
        }
    }
}

动态执行方法API

Method 类上提供了“动态执行方法”的方法

动态执行方法 API

//invoke: 调用
method.invoke(对象, 方法参数...)
//在这个对象上执行method对应的方法
//假设 method 代表 test1方法
//将对象 是 obj
//这样调用invoke相当于 obj.test1()

反射总结

  1. 反射是Java的一套API,提供了Java的动态执行功能
  2. 反射不能乱用
    • 反射API执行效率低,尽量不用
    • 如果必须动态功能,再使用!
      • 不知道类名,方法名,属性名...
  3. 反射必须了解的API
    • Class.forName()
    • cls.newInstance()
    • m.invoke()
  4. 反射API可以访问私有成员!(可以打破封装)

执行私有方法:

Method m=cls.getDeclaredMethod(
    "add", int.class, String.class)
//setAccessible 方法可以关闭原有访问控制机制!使不能执行的方法可以执行了!
m.setAccessible(true);
m.invoke(obj, 5, "abc");

获取一个指定的方法信息

API

Method m=cls.getDeclaredMethod(
    "add", int.class, String.class)

猜你喜欢

转载自blog.csdn.net/Coder_Boy_/article/details/83043568
今日推荐