Java中的reflect技术



什么是reflect技术?

网上通常将这种技术称为“反射”,我倒更希望称之为“反映”:从类的底层角度实现来反映一个类的各个部分。






Refect技术能对一个类进行反映,获得类中的成员变量和成员方法。


 


public class ReflectPoint{


  private int x;


  public int y;


  


  public String str1="blue";


  private String str2="bubble";


  public String str3="soso";


  


         publicReflectPoint(int x, int y){


                   super();


                   this.x= x;


                   this.y= y;


         }


        


         publicString toString(){


                   returnstr1+" "+str2+" "+str3;


         }


}


 


比如对于上述的ReflectPoint类,我希望通过对Field变量进行修改,将其中的b字符都修改为a字符。但是显而易见,上述类中并没有提供对应的修改接口,那我们就可以通过reflect技术来处理。


 


要进行处理,就可以使用reflect技术中的Field抽象;如果使用Field抽象的话,那么我们要做的事:


  1. 创建一个ReflectPoint实例obj

  2. 然后就要获得该类的各个成员变量(Field),获得变量域,首先需要得到Class,所以对应的代码如下:

    Field[] fields = obj.getClass().getDeclaredFields(); //此处的declared同时能应付私有和公有;

  3. 因为要修改的只有string类型,所以要排除int类型的变量;所以此处涉及如何获得field变量的属性:field.getType() == java.lang.string.class;

  4. 对于字符进行替换,有现成的方法replace();


 


具备上述要素后,我们就可以进行相应的操作。


 


实现过程遇到的问题:


  1. 如果由field获得string对象呢?

    只要简单field.get(obj)即可,呵呵。

     

  2. 处理后的字符串又如何回填到field对象中呢?

    只要field.set(obj, str); 与前述的get相对应。


 


 


第一版的实现:


import java.lang.reflect.*;


import java.util.*;


 


public class MyTest{


 


         publicstatic void main(String args[])


         {


                   ReflectPointrp = new ReflectPoint(5, 9);


                   changeValue(rp);    


                   System.out.println(rp);


         }


        


         staticvoid changeValue(Object obj){


                   Field[]fields = obj.getClass().getFields();


                  


                   for(Fieldfield : fields){


                            try{


                                     if(field.getType()== java.lang.String.class){


                                               Stringstr = (String)field.get(obj);


                                               field.set(obj,str.replace('b', 'a'));


                                     }


                            }catch(Exceptione){


                                     e.printStackTrace();


                            }


                   }


         }


}


 


上述的实现虽然编译和测试通过,但是存在问题:


         输出中,只将str1进行修改,而并没有修改str2?原因何在?


         难道没有处理str2?


我们可以在代码中插入桩点来测试:的确可以证明str2没有被处理。


那么是什么原因呢?查看下str1 str2的区别就可以看出来,原来str2是私有的;


 


那么如何能对私有的数据也处理呢?


Field.setAccessible(true);


但是修改了还是不行,原来在getFields()时,就没有获取私有的对象;所以要获取私有的对象,那么采用的语句:getDeclaredFields();


 


上述是reflect对于变量的操作,那么如果要对类中的方法进行调用,该如何操作呢?


  1. 获得方法数组:类似于获得变量数组;

    Method [] methods = obj.getClass().getMethods();


 


  1. 获得methods对象后,如何执行特定的方法?

    可以先获得对象的名字,比如method.getName().equals(“toString”);

    String str =(String)method.invoke(object, null);  

    主要的调用为此;


 


实践过程中,上述的设计基本没什么问题;代码如下:


         staticvoid callMethod(Object obj){


                   Method[]methods = obj.getClass().getMethods();


 


                   for(Methodmethod : methods){


                            Stringmethodname = method.getName();


                            if(methodname.equals("toString")){


                                     try{


                                               Objectstr = method.invoke(obj, null);


                                               System.out.println(str);


                                     }catch(Exceptione){


                                               e.printStackTrace();


                                     }


                            }


                   }


         }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值