全面剖析java反射机制

 

 一:反射的基石

 1:反射技术创建在jdk提供的Class类上,所以要掌握反射技术,首先要熟悉Class类。java

 2:经过Class类就能够获得java类中方方面面的内容<如:java类中的:构造方法(Constructor)、属性(field)、方法(method)>。spring

 3:Class  cls=?(?表明什么,你知道吗?)编程

  注:?表明字节码数组

 4:什么是字节码?tomcat

 注:java代码编译的时候,将java源程序翻译成字节码<.class>存储到硬盘上,而后类加载器将字节码加载到jvm的内存中,生成一个又一个java对象。 框架

 5:获得字节码的三种方式:jvm

        String str1="abc"ide

Class cls1=str1.getClass();<经过对象获得字节码>测试

Class cls2=String.class;<经过类获得字节码>this

Class  cls3=Class.forName("java.lang.String");<经过包名获得字节码>

注:获得了一个类的字节码,那么就能够获得字节码的所有成分,下面将一一介绍.

6:同一类型的字节码相同吗?

        System.out.println(cls1==cls2);返回:true

System.out.println(cls1==cls3);返回:true

注:说明同一类型的字节码只有一份,同一类型的字节码是相同的。

 二:字节码的简单应用<检测数据的类型>

      1: String str1="abc";

       Class cls1=str1.getClass();

       //测试String是否为基本类型的字节码,返回false;由于:String是一个类 System.out.println(cls1.isPrimitive());

      2: //int是基本类型的字节码,返回true

System.out.println(int.class.isPrimitive())

      3:   //int是基本类型,Integer是类,所以返回:false

System.out.println(int.class==Integer.class);

      4: //包装类型的基本类型的字节码比较,返回true

System.out.println(int.class==Integer.TYPE);

      5://数组不是基本类型,返回false

      System.out.println(int[].class.isPrimitive());

 三:反射调用类中构造方法

//从String类字节码中得的:参数为:StringBuffer的构造方法类 Constructor  cons=String.class.getConstructor(StringBuffer.class);

        //用获得的构造方法类来建立一个String类型的实例

String  str3=(String)cons.newInstance(new StringBuffer("abcd"));

        //用获得的实例调用方法   

        System.out.println(str3.charAt(3));

 四:反射获取类中的属性--简单应用

 1:定义类(ReflectPoint)<下面用反射技术获取该类的属性>以下:

  public class ReflectPoint {

   private int x;//私有的属性,注意看下面,反射怎样访问私有属性!

   public int y;

   public String str1="bal";

   public String str2="bseerb";

   public String str3="hjke";

  /**

   * 注意:右键->source-Construtor能够自动生成构造方法

   * @param x

   * @param y

   */

 public ReflectPoint(int x, int y) {

super();

this.x = x;

this.y = y;} 

 public String  toString(){

     return str1+":"+str2+":"+str3;

 }}

2:使用反射技术,从ReflectPoint字节码中获得属性y,代码以下:

  ReflectPoint rfp1=new ReflectPoint(3, 5);

  //从ReflectPoint的字节码中获得名为y的属性 

  Field  fieldY=rfp1.getClass().getField("y");

   //从rfp1这个对象上去取值

   System.out.println(fieldY.get(rfp1)); 结果为:5

3:使用反射技术,从ReflectPoint字节码中获得私有属性x,代码以下:

      ReflectPoint rfp1=new ReflectPoint(3, 5);

      Field  fieldX=rfp1.getClass().getDeclaredField("x");

      //由于x设置的权限为:private,所以设置强制性访问变量,这叫暴力反射 ,

       fieldX.setAccessible(true);

       System.out.println(fieldX.get(rfp1)); 结果为:3

 五:反射改变类中的属性值-综合案例应用

  1:问题?

   将类名为:ReflectPoint类中的String类型的成员变量对应的字符串内容的  "b"-改成-->"a"

  2:定义类以下<用反射来改变这个类中的属性>:

public class ReflectPoint {

   public String str1="bal";

   public String str2="bseerb";

   public String str3="hjke";

}

3:反射方法代码:

private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {

         //获得obj字节码中的所有属性

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

for(Field field:fields){

//若是是String类型

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

//取得值

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

String  newValue=oldValue.replace('b','a');

field.set(obj, newValue);

} }}

4:测试代码:

   ReflectPoint rfp1=new ReflectPoint();

  changeStringValue(rfp1);

5:结果:

    str1=aal  str2 = aseera   str3 = hjke 反射改变属性值成功!

 六:反射调用类中的方法

 1:经过反射调用string类中charAt方法 

  String str1="abc"; 

 //从string字节码中获得名为:charAt,参数类型为int.class的方法

 Method methodChAt=String.class.getMethod("charAt",int.class);            //注:invoke(str1,1)表示:对象str1调用charAt方法,传入参数为:1

 System.out.println(methodChAt.invoke(str1,1));

 七:总结

 1:掌握了以上知识,就掌握了java反射机制的基础和精髓部分。但运用反射机制到实际软件系统中,在反射的世界里,才刚刚开始。

 2:反射通常用于开发框架<如:struct/spring/Hibernate>,这些框架都是以反射技术做为支撑的。

3:掌握了反射技术便于读懂较深刻的java代码<借张孝祥的话>,我也有这样的体会。<研究tomcat源码时候,里面就运用了大量的反射技术>。

ps:在编程道路上|我才刚刚起步|加油|坚持!

                             2012-10-4 coder:亮仔

相关文章
相关标签/搜索