写点什么

Java 反射简析

用户头像
Langer
关注
发布于: 2021 年 03 月 29 日
Java反射简析

java 反射用一句话来说明,即是 java 语言提供的一系列 api,用来在运行时检测和修改类、方法、接口等运行时对象。

三个关于 java reflection 的关键点:

  • 所有有关 reflection 功能的类都定义在 java.lang.reflect 这个包内

  • 通过 reflection 使用者可以指导给定对象的类信息,以及与这个类绑定的所有方法的信息

  • 通过使用 reflection 的相关接口,使用者可以在运行时调用和修改与指定对象相关类的方法,而不需要事先知道有关这个对象类的详细信息


下面通过一个详细的例子来解释 reflection 的功能,例子中涉及到 reflection 包中十分重要的三个类:

  1. Class 类,通过指定对象的 getClass 方法调用,可以得到指定对象的类

  2. Constructors 类,通过对指定对象类 getConstructors 方法调用,可以得到指定对象类的构造函数

  3. Methods 类,通过对指定对象类 getMethods 方法调用,可以得到指定对象类的所有公共方法列表

// 一个典型的java reflection使用示例import java.lang.reflect.Method;import java.lang.reflect.Field;import java.lang.reflect.Constructor;
// 声明Test类,后面用来在其它类中展示reflection用法class Test{ // 创建私有字符串变量s private String s;
// 创建构造函数 public Test() { s = "Test"; }
// 创建无参公共方法method1 public void method1() { System.out.println("The string is " + s); }
// 创建带整形参数n的公共方法method2 public void method2(int n) { System.out.println("The number is " + n); }
// 创建一个私有方法 private void method3() { System.out.println("Private method invoked"); }}
class Demo{ public static void main(String args[]) throws Exception { // new一个Test类的实例,以供后面reflection接口使用 Test obj = new Test();
// 从obj中获取对应类,并通过getName方法获取类名称 Class cls = obj.getClass(); System.out.println("The name of class is " + cls.getName());
// 从cls实例中获取构造函数实例 Constructor constructor = cls.getConstructor(); System.out.println("The name of constructor is " + constructor.getName());
System.out.println("The public methods of class are : ");
// 从cls实例中获取其所有公共方法列表 Method[] methods = cls.getMethods();
// 打印公共方法名称 for (Method method:methods) System.out.println(method.getName());
// 传入名称和对应方法参数,获取类的方法 Method methodcall1 = cls.getDeclaredMethod("method2", int.class);
// 类方法独立与实例obj本身进行调用 methodcall1.invoke(obj, 19);
// 传属性名获得类的属性实例 Field field = cls.getDeclaredField("s");
// 改变属性访问权限为公共 field.setAccessible(true);
// 调用属性实例field的set方法,传入obj来修改obj的属性值 field.set(obj, "JAVA");
// 传入方法名称获取方法实例 Method methodcall2 = cls.getDeclaredMethod("method1");
// 如需通过obj,调用Method类实例,当然obj还是需要作为参数传入 methodcall2.invoke(obj);
// 传入方法名获取Test的私有方法method3 Method methodcall3 = cls.getDeclaredMethod("method3");
// 改变method3的访问控制为公开 methodcall3.setAccessible(true);
// 调用已改为公开访问的method3 methodcall3.invoke(obj); }}
复制代码

运行输出:

The name of class is TestThe name of constructor is TestThe public methods of class are :method2method1waitwaitwaitequalstoStringhashCodegetClassnotifynotifyAllThe number is 19The string is JAVAPrivate method invoked
复制代码

从上面的程序输出中可以看出:

  1. 只要知道某个类的方法名称和其对应的参数类型,就可以通过 getDeclareMethod 方法获取对应 reflection Method 方法实例,并使用 invoke 方法来动态调用这个 Method 实例。用法如下:

Class.getDeclareMethod(name, parametertype)name - 需要实例化的方法名称parametertype - 方法对应的参数类型列表
复制代码

如果要调用“反射”出来的方法,可以使用 Method 示例的 invoke 方法:

Method.invoke(Object, parameter)
复制代码
  1. 通过 reflection 的使用,可以改变原来类方法或者属性的访问权限,如上例所示。


小结:

通过上面的例子,可以了解到通过使用 reflection,可以很方便的在应用中集成未知的用户定义类的各项功能,也能更加方便的调试现有程序,当然 reflection 的使用也增加了程序本身对外信息暴露的风险。


发布于: 2021 年 03 月 29 日阅读数: 12
用户头像

Langer

关注

还未添加个人签名 2021.03.22 加入

还未添加个人简介

评论

发布
暂无评论
Java反射简析