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中的私有方法。

  相关博文:Java中的反射机制(四)
利用反射访问私有

  访问私有方法有一个关键点:


setAccessible(true); // 抑制Java对修饰符的检查

  这个方法是AccessibleObject类中的。

  前面说过,它是FieldMethodConstructor<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]

  可见Integerint被认为是两种类型,所以调用方法的时候,类型参数也还是从外部传入比较科学。

  修改后的调用方法如下:


    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类参考:

  参考1:https://svn.apache.org/repos/asf/webservices/muse/trunk/modules/muse-util/src/org/apache/muse/util/ReflectUtils.java

  参考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类的编写和对反射机制的解析

时间: 2024-10-31 22:00:35

ReflectUitls类的编写和对反射机制的解析的相关文章

工具类之数据库工具类:DBUtil(采用反射机制)

经常操作数据库的码农们一定知道操作数据库是一项很复杂的工作,它不仅要解决各种乱码的问题还要解决各种数据表的增删改查等的操作. 另外每次操作数据库都要用到数据库连接.执行SQL语句.关闭连接的操作,所以在这里我就把这些功能封装到了一个工具类中,该类使用的是反射机制写成的,也就是说它可以帮助你完成对任何数据表的操作.关键代码如下: 首先是配置文件:config.properties driverName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost

java 类的加载及反射机制

一,类的加载,连接,初始化 一个类被加载到JVM需要三个步骤:加载,链接,初始化 1,先说下加载过程 2,连接 注意连接过程分为三个阶段,验证,准备,解析 3,初始化 这里注意:类的加载过程,先加载静态代码块,其次是代码块,然后是构造函数 静态成员之间级别一样,因此谁在前,谁最先被加载 二,反射机制 1,先理解下反射 2,为什么要使用反射 可能以上叙述依然很抽象,下面我们用具题代码说明 在开始代码之前我们要先,明白一个对象 java.lang.Class 我们可以这样想,java程序在运行前,会

Java反射机制实例解析

1.获取想操作的访问类的java.lang.Class类的对象     2.调用Class对象的方法返回访问类的方法和属性信息     3.使用反射API来操作      每个类被加载后,系统会为该类生成一个对应的Class对象,通过该Class对象就可以访问到Java虚拟机中的这个类,Java程序中获取Class对象通常有如下三种方式: 1.调用某个对象的getClass()方法,是Object中的一个方法,所以所有类都可以调用这个方法 Person p= new Person(); Clas

Java反射机制及IoC原理

一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 类中有什么信息,利用反射机制就能可以获得什么信息,不过前提是得知道类的名字. 二. 反射机制的作用 在运行时判断任意

【java基础】Java反射机制

一.预先需要掌握的知识(java虚拟机)  1)java虚拟机的方法区:  java虚拟机有一个运行时数据区,这个数据区又被分为方法区,堆区和栈区,我们这里需要了解的主要是方法区.方法区的主要作用是存储被装载的类 的类型信息,当java虚拟机装载某个类型的时候,需要类装载器定位相应的class文件,然后将其读入到java虚拟机中,紧接着虚拟机提取class 中的类型信息,将这些信息存储到方法区中.这些信息主要包括: 这个类型的全限定名 这个类型的直接超类的全限定名 这个类型是类类型还是接口类型

java 反射机制的概念

java 反射 定义 功能 示例 概要: Java反射机制详解 | |目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为Integer的Arr

粗浅看 java反射机制

什么是  Java 反射是 Java 被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运 行时透过 Reflection APIs 取得任何一个已知名称的class 的内部信息,包括其 modifiers( 诸如 public, static 等 ).superclass (例如 Object). 实现之 interfaces(例如 Cloneable),也包括 fields 和 methods 的所有信息,并可于运行时改变 fields 内容或唤起 methods. Java 反射

[转]Java反射机制详解

目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为Integer的ArrayList中存放一个String类型的对象. ·通过反射取得并修改数

JAVA反射机制—学习总结

最近收到很多关于Java反射机制的问题留言,其实Java反射机制技术方面没有太多难点,或许是大家在学习过程中遗漏了细小知识点,导致一些问题无法彻底理解,现在我们简单的总结一下,加深印象. 什么是反射机制? "JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制."我们通过一些例子,更好理解反射机制.Class类 我们知道Java是一门面向对象