ReflectUitls类的编写和对反射机制的解析
ReflectUitls类的编写和对反射机制的解析
反射相关的类
反射相关的类,最基本的当然是Class类。
获取了Class对象之后,就可以接着生成对象实例、调用方法、查看字段等等。
字段(Field)、方法(Method)和构造方法(Constructor<T>)各有相应的类来表示,它们共同继承于java.lang.reflect.AccessibleObject类:
这三个类共同实现的还有Member接口:
获取字段、方法和构造方法时,需要调用Class类的getXXX()和getDeclearedXXX()方法,需要注意二者区别。
比如对于方法:
- getMethods();//获取public (包括父类中的)
- getDeclaredMethods();//获取本类声明(包括各种修饰符public、private)
相关博文:Java中的反射机制(一)
API 文档:http://docs.oracle.com/javase/7/docs/api/
访问权限相关
利用反射,可以访问一些SDK、API中的私有方法。
访问私有方法有一个关键点:
- setAccessible(true); // 抑制Java对修饰符的检查
这个方法是AccessibleObject类中的。
前面说过,它是Field、Method和Constructor<T>的共同基类。
正常情况下,调用isAccessible()返回的都是false,无论你的方法是public还是private。
这是因为这个accessible的flag是JVM用来限制是否可以直接访问,默认情况下是需要进行访问修饰符的检查的,所以flag为false,即不能直接访问。
当这个flag设置为true,表明可以直接访问,不经过访问修饰符的检查。
辅助类中用于调用私有方法的接口:
- /**
- * 调用私有方法
- *
- * @param obj
- * 调用类对象
- * @param methodName
- * 方法名
- * @param paramTypes
- * 参数类型
- * @param params
- * 参数
- * @return
- * @throws Exception
- */
- public static Object invokePrivateMethod(Object obj, String methodName,
- Class<?>[] paramTypes, Object[] params) throws Exception {
- Object value = null;
- Class<?> cls = obj.getClass();
- // 注意不要用getMethod(),因为getMethod()返回的都是public方法
- Method method = cls.getDeclaredMethod(methodName, paramTypes);
- method.setAccessible(true);// 抑制Java的访问控制检查
- value = method.invoke(obj, params);
- return value;
- }
访问修饰符
对访问修饰符的获取可以通过Member接口的getModifiers()方法,该方法返回一个整型值,整型值是一系列的修饰符位操作组合的结果。
用Modifier类可以解析这个整型值中包含的修饰符信息。
- /**
- * 获取修饰符信息
- *
- * @param member
- * @return
- */
- private static String getModifiersInfo(Member member) {
- StringBuilder sBuilder = new StringBuilder();
- int modifiers = member.getModifiers();
- sBuilder.append("\ngetModifiers: " + +modifiers + ", ");// 得到修饰符编码
- sBuilder.append("\nisPublic: " + Modifier.isPublic(modifiers) + ", ");
- sBuilder.append("\nisPrivate: " + Modifier.isPrivate(modifiers) + ", ");
- sBuilder.append("\nisStatic: " + Modifier.isStatic(modifiers) + ", ");
- sBuilder.append("\nisFinal: " + Modifier.isFinal(modifiers) + ", ");
- sBuilder.append("\nisAbstract: " + Modifier.isAbstract(modifiers));
- return sBuilder.toString();
- }
包装类与原生数据类型
相关博文: Java 包装类 自动装箱和拆箱
写了一个调用静态方法的辅助类,我本来是这么写的:
- /*
- * wrong:
- * public static Object invokePublicStaticMethod(String className,
- * String methodName, Object[] params) throws Exception {
- *
- * Class<?> cls = Class.forName(className);
- * Class<?>[] paramTypes = new Class<?>[params.length];
- * for (int i = 0; i < params.length; ++i) {
- * paramTypes[i] = params[i].getClass();
- *
- * }
- * Method method = cls.getMethod(methodName, paramTypes);
- * Object value = null;
- * if (isPublicStatic(method)) {
- * value = method.invoke(null, params);
- * }
- *
- * return value;
- * }
- */
意图是只传入参数数组,在内部自己根据参数获取类型数组,可以少传点参数,但是这样遇到了问题。
在Example类里写了这么三个测试方法:
- public static void printSomething(String line) {
- System.out.println(line);
- }
- public static int add(int a, int b) {
- return a + b;
- }
- public static double getPi() {
- return 3.14159d;
- }
测试的时候发现参数是String类型的时候可以正常执行,但是参数如果是原生数据类型(int类型),用这个方法调用时就跑出了异常:
java.lang.NoSuchMethodException: com.mengdd.reflect.Example.add(java.lang.Integer, java.lang.Integer)
测试了一下:
- Object[] array = new Object[] { 1, 2 };
- System.out.println("getClass(): " + array[0].getClass());
- System.out.println("Integer.TYPE: " + Integer.TYPE);
输出:
- getClass(): class java.lang.Integer
- Integer.TYPE: int
而那个用于测试的add()方法:
- getReturnType: int
- getParameterTypes: [int, int]
可见Integer和int被认为是两种类型,所以调用方法的时候,类型参数也还是从外部传入比较科学。
修改后的调用方法如下:
- public static Object invokePublicStaticMethod(String className,
- String methodName, Class<?>[] paramTypes, Object[] params)
- throws Exception {
- Class<?> cls = Class.forName(className);
- Method method = cls.getMethod(methodName, paramTypes);
- Object value = null;
- if (isPublicStatic(method)) {
- value = method.invoke(null, params);
- }
- return value;
- }
测试代码:
- Object result1 = ReflectUtils.invokePublicStaticMethod(
- "com.mengdd.reflect.Example", "add", new Class<?>[] {
- int.class, Integer.TYPE }, new Object[] { 1, 2 });
- // int.class和Integer.TYPE都行
- Assert.assertEquals(3, result1);
ReflectUtils类
ReflectUtils类完整代码如下:
- package com.mengdd.reflect;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Member;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.util.Arrays;
- /**
- *
- * @ClassName ReflectUtils
- * @Description Reflection Helper class
- *
- * @author mengdandan
- * @Date 2014年5月13日上午10:40:32
- *
- */
- public class ReflectUtils {
- /**
- * 创建类的实例,调用类的无参构造方法
- *
- * @param className
- * @return
- */
- public static Object newInstance(String className) {
- Object instance = null;
- try {
- Class<?> clazz = Class.forName(className);
- instance = clazz.newInstance();
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- catch (InstantiationException e) {
- // if this Class represents an abstract class, an interface, an
- // array class, a primitive type, or void; or if the class has no
- // nullary constructor; or if the instantiation fails for some other
- // reason.
- e.printStackTrace();
- }
- catch (IllegalAccessException e) {
- // if the class or its nullary constructor is not accessible
- e.printStackTrace();
- }
- return instance;
- }
- /**
- * 获取所有的public构造方法的信息
- *
- * @param className
- * @return
- */
- public static String getPublicConstructorInfo(String className) {
- StringBuilder sBuilder = new StringBuilder();
- try {
- Class<?> clazz = Class.forName(className);
- Constructor<?>[] constructors = clazz.getConstructors();
- sBuilder.append(getConstructorInfo(constructors));
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- return sBuilder.toString();
- }
- /**
- * 得到本类内声明的构造方法信息
- *
- * @param className
- * @return
- */
- public static String getDeclearedConstructorInfo(String className) {
- StringBuilder sBuilder = new StringBuilder();
- try {
- Class<?> clazz = Class.forName(className);
- Constructor<?>[] constructors = clazz.getDeclaredConstructors();
- sBuilder.append(getConstructorInfo(constructors));
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- return sBuilder.toString();
- }
- /**
- * 获取public的字段信息
- *
- * @param className
- * @return
- */
- public static String getPublicFieldInfo(String className) {
- StringBuilder sBuilder = new StringBuilder();
- try {
- Class<?> clazz = Class.forName(className);
- Field[] fields = clazz.getFields();
- sBuilder.append(getFieldInfo(fields));
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- return sBuilder.toString();
- }
- /**
- * 获取本类内声明的字段信息
- *
- * @param className
- * @return
- */
- public static String getDecleardFieldInfo(String className) {
- StringBuilder sBuilder = new StringBuilder();
- try {
- Class<?> clazz = Class.forName(className);
- Field[] fields = clazz.getDeclaredFields();
- sBuilder.append(getFieldInfo(fields));
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- return sBuilder.toString();
- }
- /**
- * 得到所有public方法信息
- *
- * @param className
- * @return
- */
- public static String getPublicMethodInfos(String className) {
- StringBuilder sBuilder = new StringBuilder();
- try {
- Class<?> clazz = Class.forName(className);
- Method[] methods = clazz.getMethods();// 得到所有的public方法,包括从基类继承的
- sBuilder.append(getMethodInfo(methods));
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- return sBuilder.toString();
- }
- /**
- * 得到类内声明的方法信息
- *
- * @param className
- * @return
- */
- public static String getDeclaredMethodInfos(String className) {
- StringBuilder sBuilder = new StringBuilder();
- try {
- Class<?> clazz = Class.forName(className);
- Method[] methods = clazz.getDeclaredMethods();// 得到本类声明的所有方法,包括私有方法
- // clazz.getMethods(); 会返回所有public的方法,但是包括基类Object的方法
- sBuilder.append(getMethodInfo(methods));
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- return sBuilder.toString();
- }
- /**
- * 得到构造器信息
- *
- * @param constructor
- * @return
- */
- private static String getConstructorInfo(Constructor<?> constructor) {
- StringBuilder sBuilder = new StringBuilder();
- sBuilder.append("name: " + constructor.getName());
- sBuilder.append("\ngetParameterTypes: "
- + Arrays.toString(constructor.getParameterTypes()));
- return sBuilder.toString();
- }
- /**
- * 将一组构造器的信息组成一个字符串返回
- *
- * @param constructors
- * @return
- */
- private static String getConstructorInfo(Constructor<?>[] constructors) {
- StringBuilder sBuilder = new StringBuilder();
- int i = 0;
- for (Constructor<?> c : constructors) {
- sBuilder.append("method: " + ++i + " : ");
- sBuilder.append("\n" + getConstructorInfo(c));
- sBuilder.append("\n");
- }
- return sBuilder.toString();
- }
- /**
- * 获取字段信息,组成一个字符串返回
- *
- * @param field
- * @return
- */
- private static String getFieldInfo(Field field) {
- StringBuilder sBuilder = new StringBuilder();
- sBuilder.append("name: " + field.getName());
- sBuilder.append("\ngetType: " + field.getType());
- sBuilder.append(getModifiersInfo(field));
- return sBuilder.toString();
- }
- /**
- * 获取一组字段的信息,返回字符串
- *
- * @param fields
- * @return
- */
- private static String getFieldInfo(Field[] fields) {
- StringBuilder sBuilder = new StringBuilder();
- int i = 0;
- for (Field field : fields) {
- sBuilder.append("field: " + ++i + " : ");
- sBuilder.append("\n" + getFieldInfo(field));
- sBuilder.append("\n");
- }
- return sBuilder.toString();
- }
- /**
- * 获取方法的信息,组成一个字符串返回
- *
- * @param method
- * @return
- */
- private static String getMethodInfo(Method method) {
- StringBuilder sBuilder = new StringBuilder();
- sBuilder.append("name: " + method.getName());
- sBuilder.append("\ngetReturnType: " + method.getReturnType());
- sBuilder.append("\ngetParameterTypes: "
- + Arrays.toString(method.getParameterTypes()));
- sBuilder.append(getModifiersInfo(method));
- return sBuilder.toString();
- }
- /**
- * 获取一组方法的信息,组成一个字符串返回
- *
- * @param methods
- * @return
- */
- private static String getMethodInfo(Method[] methods) {
- StringBuilder sBuilder = new StringBuilder();
- int i = 0;
- for (Method method : methods) {
- sBuilder.append("method: " + ++i + " : ");
- sBuilder.append("\n" + getMethodInfo(method));
- sBuilder.append("\n");
- }
- return sBuilder.toString();
- }
- /**
- * 获取修饰符信息
- *
- * @param member
- * @return
- */
- private static String getModifiersInfo(Member member) {
- StringBuilder sBuilder = new StringBuilder();
- int modifiers = member.getModifiers();
- sBuilder.append("\ngetModifiers: " + +modifiers + ", ");// 得到修饰符编码
- sBuilder.append("\nisPublic: " + Modifier.isPublic(modifiers) + ", ");
- sBuilder.append("\nisPrivate: " + Modifier.isPrivate(modifiers) + ", ");
- sBuilder.append("\nisStatic: " + Modifier.isStatic(modifiers) + ", ");
- sBuilder.append("\nisFinal: " + Modifier.isFinal(modifiers) + ", ");
- sBuilder.append("\nisAbstract: " + Modifier.isAbstract(modifiers));
- return sBuilder.toString();
- }
- /**
- * 是否是公用静态方法
- *
- * @param member
- * @return
- */
- private static boolean isPublicStatic(Member member) {
- boolean isPS = false;
- int mod = member.getModifiers();
- isPS = Modifier.isPublic(mod) && Modifier.isStatic(mod);
- return isPS;
- }
- /**
- * 调用静态方法
- *
- * @param className
- * @param methodName
- * @param paramTypes
- * @param params
- * @return
- * @throws Exception
- */
- public static Object invokePublicStaticMethod(String className,
- String methodName, Class<?>[] paramTypes, Object[] params)
- throws Exception {
- Class<?> cls = Class.forName(className);
- Method method = cls.getMethod(methodName, paramTypes);
- Object value = null;
- if (isPublicStatic(method)) {
- value = method.invoke(null, params);
- }
- return value;
- }
- /*
- * wrong:
- * public static Object invokePublicStaticMethod(String className,
- * String methodName, Object[] params) throws Exception {
- *
- * Class<?> cls = Class.forName(className);
- * Class<?>[] paramTypes = new Class<?>[params.length];
- * for (int i = 0; i < params.length; ++i) {
- * paramTypes[i] = params[i].getClass();
- *
- * }
- * Method method = cls.getMethod(methodName, paramTypes);
- * Object value = null;
- * if (isPublicStatic(method)) {
- * value = method.invoke(null, params);
- * }
- *
- * return value;
- * }
- */
- /**
- * 调用私有方法
- *
- * @param obj
- * 调用类对象
- * @param methodName
- * 方法名
- * @param paramTypes
- * 参数类型
- * @param params
- * 参数
- * @return
- * @throws Exception
- */
- public static Object invokePrivateMethod(Object obj, String methodName,
- Class<?>[] paramTypes, Object[] params) throws Exception {
- Object value = null;
- Class<?> cls = obj.getClass();
- // 注意不要用getMethod(),因为getMethod()返回的都是public方法
- Method method = cls.getDeclaredMethod(methodName, paramTypes);
- method.setAccessible(true);// 抑制Java的访问控制检查
- value = method.invoke(obj, params);
- return value;
- }
- }
ReflectUtils.java
测试类和测试代码:
- package com.mengdd.reflect;
- public class Example {
- private String mFiledOne = null;
- private int mCount = 0;
- private double mNum = 6;
- public int mPub = 4;
- public Example() {
- }
- public Example(String filedOne, int count, double num) {
- super();
- this.mFiledOne = filedOne;
- this.mCount = count;
- this.mNum = num;
- }
- public String getFiledOne() {
- return mFiledOne;
- }
- public void setFiledOne(String filedOne) {
- this.mFiledOne = filedOne;
- }
- public int getCount() {
- return mCount;
- }
- public void setCount(int count) {
- this.mCount = count;
- }
- public double getNum() {
- return mNum;
- }
- public void setNum(double num) {
- this.mNum = num;
- }
- public static void printSomething(String line) {
- System.out.println(line);
- }
- public static int add(int a, int b) {
- return a + b;
- }
- public static double getPi() {
- return 3.14159d;
- }
- @Override
- public String toString() {
- return "Example [mFiledOne=" + mFiledOne + ", mCount=" + mCount + "]";
- }
- private String tellSecret(String name, int num) {
- String result = name + num + toString();
- return result;
- }
- }
Example.java
- package com.mengdd.reflect;
- import org.junit.Assert;
- import org.junit.Test;
- public class ReflectTest {
- @Test
- public void testNewInstance() {
- Object object = ReflectUtils.newInstance("com.mengdd.reflect.Example");
- Assert.assertNotNull(object);
- }
- @Test
- public void testGetConstructorInfo() {
- String result = ReflectUtils
- .getPublicConstructorInfo("com.mengdd.reflect.Example");
- System.out
- .println("=============testGetConstructorInfo================");
- System.out.println(result);
- System.out
- .println("===================================================");
- Assert.assertNotNull(result);
- }
- @Test
- public void testFieldInfos() {
- String result = ReflectUtils
- .getDecleardFieldInfo("com.mengdd.reflect.Example");
- System.out.println("=============testFieldInfos================");
- System.out.println(result);
- System.out
- .println("===================================================");
- Assert.assertNotNull(result);
- }
- @Test
- public void testMethodInfos() {
- String result = ReflectUtils
- .getDeclaredMethodInfos("com.mengdd.reflect.Example");
- System.out.println("=============testMethodInfos================");
- System.out.println(result);
- System.out
- .println("===================================================");
- Assert.assertNotNull(result);
- }
- @Test
- public void testPublicStaticInvocation() {
- System.out
- .println("=============test static invocation================");
- try {
- // 静态方法1
- ReflectUtils.invokePublicStaticMethod("com.mengdd.reflect.Example",
- "printSomething", new Class<?>[] { String.class },
- new Object[] { "Hello World" });
- // 静态方法2
- Object result1 = ReflectUtils.invokePublicStaticMethod(
- "com.mengdd.reflect.Example", "add", new Class<?>[] {
- int.class, Integer.TYPE }, new Object[] { 1, 2 });
- // int.class和Integer.TYPE都行
- Assert.assertEquals(3, result1);
- // 静态方法3
- Object result2 = ReflectUtils.invokePublicStaticMethod(
- "com.mengdd.reflect.Example", "getPi", new Class<?>[] {},
- new Object[] {});
- Assert.assertEquals(3.14159, result2);
- }
- catch (Exception e) {
- e.printStackTrace();
- System.out.println("Exception!");
- }
- System.out
- .println("===================================================");
- }
- @Test
- public void testPrivateInvocation() {
- Example example = new Example("1", 5, 0);
- Object secret = null;
- try {
- secret = ReflectUtils.invokePrivateMethod(example, "tellSecret",
- new Class<?>[] { String.class, Integer.TYPE },
- new Object[] { "Hello", 2 });
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- String expected = "Hello2Example [mFiledOne=1, mCount=5]";
- Assert.assertEquals(expected, secret);
- }
- }
ReflectTest.java
预计后期还会有进一步更新完善,项目地址等待补充。
参考资料
Java 2 SE 7 API文档:http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/package-summary.html
ReflectUtils类参考:
参考2:http://www.oschina.net/code/snippet_736664_16425
参考3:http://www.oschina.net/code/explore/cglib-2.2/src/proxy/net/sf/cglib/core/ReflectUtils.java
ReflectUitls类的编写和对反射机制的解析的更多相关文章
- Java反射机制(Reflect)解析-----https://www.cnblogs.com/fzz9/p/7738381.html
Java反射机制(Reflect)解析-----https://www.cnblogs.com/fzz9/p/7738381.html
- Java反射机制(Reflect)解析
一.导读 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语言的设计 ...
- 分享知识-快乐自己:反射机制Demo解析
Java-Reflect专题 基本反射简介: 1):JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象能够调用它的任意方法和属性;这种动态获取信息以及动 ...
- Java反射机制实例解析
1.获取想操作的访问类的java.lang.Class类的对象 2.调用Class对象的方法返回访问类的方法和属性信息 3.使用反射API来操作 每个类被加载后,系统会为该类 ...
- java中的反射机制,以及如何通过反射获取一个类的构造方法 ,成员变量,方法,详细。。
首先先说一下类的加载,流程.只有明确了类这个对象的存在才可以更好的理解反射的原因,以及反射的机制. 一. 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三 ...
- Java反射机制及IoC原理
一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通 ...
- 【Java基础】反射机制
反射 反射可以使我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码链接.反射允许我们在编写和执行时,使我们的代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类 ...
- Java反射机制详解(1) -反射定义
首先,我们在开始前提出一个问题: 1.在运行时,对于一个java类,能否知道属性和方法:能否去调用它的任意方法? 答案是肯定的. 本节所有目录如下: 什么是JAVA的反射机制 JDK中提供的Refle ...
- [转]Java反射机制详解
目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详 ...
随机推荐
- Android序列化之Serializable和Parcelable
PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...
- Django之路由、模板和模型系统
一.路由系统 浏览器会自动给url后加一个"/" django会自动给路由的正则表达式前面加一个"/" django会给任何不带"/"结尾的 ...
- HTML语义化:HTML5的新标签及IE5.5~9的部分兼容方案
一.前言 本文将介绍HTML5中新增的语义化标签,及在IE5.5~9(IE9已经开始支持部分HTML5新标签了)支持这些新标签的兼容性处理. 目录一坨: 二.语义化标签:article.aside.t ...
- Vue2.0流式渲染中文乱码问题
在参照vue2.0中文官方文档学习服务端渲染之流式渲染时,因为响应头默认编码类型为GBK,而文件为UFT-8类型,所以出现了中文乱码问题. 解决办法:设置响应头编码类型即可 response.setH ...
- android studio building project info 错误
D:\ProgramFiles\android-studio\plugins\android\lib\templates\gradle\wrapper\gradle\wrapper\gradle-wr ...
- AMD64和i386的区别
下载Debian系统时,出现两个选项:ADM64和i386,那么这两者的区别是什么? i386=Intel 80386.其实i386通常被用来作为对Intel(英特尔)32位微处理器的统称. AMD6 ...
- 检测IP地址的正则表达式
正则表达式: ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) ((2[0-4]\d|25[0-5]|[01]?\d\ ...
- ASP.NET发送电子邮件
代码: using System; using System.Collections.Generic; using System.Configuration; using System.Linq; u ...
- Socket开发框架之数据传输协议
我在前面一篇随笔<Socket开发框架之框架设计及分析>中,介绍了整个Socket开发框架的总体思路,对各个层次的基类进行了一些总结和抽象,已达到重用.简化代码的目的.本篇继续分析其中重要 ...
- CIO:让IT成为企业的一种竞争优势
在你的公司,IT是将自己视为服务提供者,业务部门的合作伙伴,还是创新驱动者?其他部门的领导者是怎么看待IT的?在老板的眼里,IT是如何的一个定位?在过去一年的,身为企业的CIO,你是否知道哪些应用或新 ...