上一篇介绍了java反射的基本概念,并通过一个简单的例子展示了如何获取一个类所定义的变量和方法
下面将介绍如何通过反射来访问类里面的方法,先看一个例子
- importjava.lang.reflect.AccessibleObject;
- importjava.lang.reflect.Field;
- importjava.lang.reflect.Method;
- publicclassTest{
- privateStringname;
- publicStringgetName(){
- returnname;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- System.out.println("初始化name属性:"+name);
- }
- publicstaticvoidmain(String[]args){
- System.out.println("show方法的输出:");
- show(newTest());
- System.out.println("getSetMethod方法的输出:");
- getSetMethod(newTest());
- }
- @SuppressWarnings("unchecked")
- publicstaticvoidshow(Objectclazz){
- try{
- /**
- *获取类里面的setName方法并指定其参数是String类型
- */
- MethodsetName=clazz.getClass().getMethod("setName",newClass[]{String.class});
- /**
- *调用setName方法,并指定参数为"zhjb"
- */
- setName.invoke(clazz,"zhjb");
- /**
- *获取类里面的getName方法
- */
- MethodgetName=clazz.getClass().getMethod("getName");
- /**
- *调用getName方法,并打印其返回值
- */
- System.out.println(getName.invoke(clazz));
- }catch(Exceptione){
- e.printStackTrace();
- }
- }
- @SuppressWarnings("unchecked")
- publicstaticvoidgetSetMethod(Objectclazz){
- try{
- /**
- *得到定义的变量
- */
- Field[]field=clazz.getClass().getDeclaredFields();
- /**
- *设置访问权限,即使是private也能访问
- */
- AccessibleObject.setAccessible(field,true);
- /**
- *给该变量赋值
- */
- field[0].set(clazz,"zhjb");
- System.out.println(field[0].get(clazz));
- }catch(Exceptione){
- 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-ddHH:mm:SS
- *因为只是介绍反射的用法,所以本方法只是做演示,肯定有很多的BUG,Object里面的属性没有自己定义的类
- *如果实际工程中可以使用org.apache.commons.beanutils.BeanUtils.copyProperties()方法
- *@paramobj
- *@paramrequest
- *@throwsParseException
- */
- @SuppressWarnings("unchecked")
- publicstaticvoidcopyProperties(Objectobj,HttpServletRequestrequest)throwsException{
- /**
- *得到定义的变量
- */
- Field[]field=obj.getClass().getDeclaredFields();
- Class[]clazz=newClass[1];
- for(Fieldf:field){
- Objectvalue=request.getParameter(f.getName());
- if(value==null){
- continue;
- }
- StringmethodName=getMethodName(f.getName());
- if(f.getType().getName().equals("java.util.Date")){
- SimpleDateFormatsf=newSimpleDateFormat("yyyy-MM-ddHH:mm:SS");
- value=sf.parse(value.toString());
- clazz[0]=Date.class;
- }elseif(f.getType().getName().equals(Integer.class.getName())){
- clazz[0]=Integer.class;
- value=newInteger(value.toString());
- }elseif(f.getType().getName().equals(String.class.getName())){
- clazz[0]=String.class;
- }
- Methodmethod=obj.getClass().getDeclaredMethod(methodName,clazz);
- method.invoke(obj,value);
- }
- }
- /**
- *把属性的第一个字母变为大写,然后在前面加上set,给该属性赋值,这是JavaBean的标准命名规则
- *@paramfieldName
- */
- publicstaticStringgetMethodName(StringfieldName){
- charc=fieldName.charAt(0);
- if(c>='a'&&c<='z'){
- c=(char)(c-'a'+'A');
- }
- return"set"+c+fieldName.substring(1);
- }
注:Java里面的属性必须是对象,有代码就可以去看如何实现了