上一篇介绍了java反射的基本概念,并通过一个简单的例子展示了如何获取一个类所定义的变量和方法
下面将介绍如何通过反射来访问类里面的方法,先看一个例子
- import java.lang.reflect.AccessibleObject;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- public class Test {
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- System.out.println("初始化name属性:"+name);
- }
- public static void main(String[] args) {
- System.out.println("show方法的输出:");
- show(new Test());
- System.out.println("getSetMethod方法的输出:");
- getSetMethod(new Test());
- }
- @SuppressWarnings("unchecked")
- public static void show(Object clazz){
- try {
- /**
- * 获取类里面的setName方法 并指定其参数是String类型
- */
- Method setName=clazz.getClass().getMethod("setName", new Class[]{String.class});
- /**
- * 调用setName方法,并指定参数为"zhjb"
- */
- setName.invoke(clazz, "zhjb");
- /**
- * 获取类里面的getName方法
- */
- Method getName=clazz.getClass().getMethod("getName");
- /**
- * 调用getName方法,并打印其返回值
- */
- System.out.println(getName.invoke(clazz));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @SuppressWarnings("unchecked")
- public static void getSetMethod(Object clazz){
- try {
- /**
- * 得到定义的变量
- */
- Field[] field=clazz.getClass().getDeclaredFields();
- /**
- * 设置访问权限,即使是private也能访问
- */
- AccessibleObject.setAccessible(field, true);
- /**
- * 给该变量赋值
- */
- field[0].set(clazz, "zhjb");
- System.out.println(field[0].get(clazz));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
运行上面的代码输出结果为:
show方法的输出:
初始化name属性:zhjb
zhjb
getSetMethod方法的输出:
zhjb
由输出的结果可以看出,show方法里面通过调用类里面的set方法给变量name赋值,而getSetMethod方法里面是直接对类里面成员变量赋值,应为 AccessibleObject.setAccessible(field, true);这样设置了访问权限,那么即使是private 也能进行直接的赋值,但是这种方法并不是很好,破坏了JavaBean的规则,所以建议使用通过get 、set的方法来访问Java类。上面的例子都写了注释了,就不在细说了。
下面看一个例子,就是把request里面的参数根据名字封装到一个JavaBean里面
- /**
- * 把request对象里面的属性拷贝到一个标准的JavaBean里面,时间格式默认为yyyy-MM-dd HH:mm:SS
- * 因为只是介绍反射的用法,所以本方法只是做演示,肯定有很多的BUG,Object 里面的属性没有自己定义的类
- * 如果实际工程中可以使用org.apache.commons.beanutils.BeanUtils.copyProperties()方法
- * @param obj
- * @param request
- * @throws ParseException
- */
- @SuppressWarnings("unchecked")
- public static void copyProperties(Object obj,HttpServletRequest request) throws Exception{
- /**
- * 得到定义的变量
- */
- Field[] field=obj.getClass().getDeclaredFields();
- Class[] clazz =new Class[1];
- for(Field f:field){
- Object value =request.getParameter(f.getName());
- if(value==null){
- continue;
- }
- String methodName=getMethodName(f.getName());
- if(f.getType().getName().equals("java.util.Date")){
- SimpleDateFormat sf= new SimpleDateFormat("yyyy-MM-dd HH:mm:SS");
- value=sf.parse(value.toString());
- clazz[0]=Date.class;
- }else if(f.getType().getName().equals(Integer.class.getName())){
- clazz[0]=Integer.class;
- value=new Integer(value.toString());
- }else if(f.getType().getName().equals(String.class.getName())){
- clazz[0]=String.class;
- }
- Method method=obj.getClass().getDeclaredMethod(methodName, clazz);
- method.invoke(obj, value);
- }
- }
- /**
- * 把属性的第一个字母变为大写,然后在前面加上set,给该属性赋值,这是JavaBean的标准命名规则
- * @param fieldName
- */
- public static String getMethodName(String fieldName){
- char c=fieldName.charAt(0);
- if(c>='a'&&c<='z'){
- c=(char)(c-'a'+'A');
- }
- return "set"+c+fieldName.substring(1);
- }
注:Java里面的属性必须是对象,有代码就可以去看如何实现了