Java反射

反射的概念:

         反射就是把java類中的各種成份映射成相應的java類。例如,一個java類中的用一個Class類的對象來表示,一個類中的組成部分,成員變量、方法、構造函數、包等等信息也用一個個java類來表示。表示java類的Class類顯然要提供一系列的方法,來獲得其中的變量、方法、構造函數、修飾 符、包等信息,這些類就是用相應的類的實例對象來表示,他們是Filed、Method、Constructor、Package等。

         一個類中的每個成員都可以用相應的反射API類的一個實例對象來表示,通過調用Class類的方法可以得到這些實例對象

 

 

反射的用途:

         反射的主要作用是:用來擴展系統和動態調用程序集。
         擴展系統
:就是先把系統寫好,系統裏面定義接口,後面開發的人去寫接口的代碼。
此時該系統就要用反射了,系統用反射調用接口,當接口沒寫,系統利用反射就不會不會出錯,此時就等於沒實現此功能而已,當接口被人寫好了,系統就會自動調用接口的功能展現在系統上。即反射實現即插即用功能。

        動態調用程序集就是利用反射去調用編譯好的程序,反射具有一定靈活性,不需改變你所建的工程。

 

反射最主要的用戶適用於做框架的

 

反射的基石-Class類:

如何得到各個字節碼對應的實例對象

類名:class,例如System.class

對象.getClass(),例如,new Date().getClass();

Class.forName(“類名”),例如Class.forName(“java.util.Date”);

 

publicclassReflectDemo1 {

 

    publicstaticvoid main(String[] args) throwsException {

        Stringstr1 = "abc";

        //得到字節碼的三種方式

        Classcls1 =str1.getClass();

        Classcls2 = String.class;

        Classcls3 = Class.forName("java.lang.String");

        System.out.println(cls1 == cls2);//true

        System.out.println(cls1 == cls3);//true

       

        //打印出是否是基本類型

        System.out.println(cls1.isPrimitive());//false

        System.out.println(int.class.isPrimitive());//true

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

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

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

        System.out.println(int[].class.isArray());//true

    }

 

}

 

總之,只要在源程序中出現的類型,都有各自的Class實例對象,例如int[],void

 

得到字節碼的三種方式:

publicclassReflectDemo1 {

 

   publicstaticvoidmain(String[] args) throws Exception {

      Stringstr1 = "abc";

      //得到字節碼的三種方式

      Classcls1 =str1.getClass();

      Classcls2 = String.class;

      Classcls3 = Class.forName("java.lang.String");

      System.out.println(cls1 == cls2);//true

      System.out.println(cls1 == cls3);//true

     

      //打印出是否是基本類型

      System.out.println(cls1.isPrimitive());//false

      System.out.println(int.class.isPrimitive());//true

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

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

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

      System.out.println(int[].class.isArray());//true

}

 

成員構造函數的反射:

使用到的ReflectPoint

publicclassReflectPoint {

   privateintx;

   publicinty;

   public ReflectPoint(int x, int y) {

      super();

      this.x = x;

      this.y = y;

  

}

 

publicclassReflectDemo2 {

 

   publicstaticvoidmain(String[] args) throws Exception {

//new String(new StringBuilder("abc"));

      //得到類型

      Constructorconstructor1= String.class.getConstructor(StringBuilder.class);

      //得到方法的對象

      Stringstr2 = (String) constructor1.newInstance(new StringBuilder("c"));

      System.out.println(str2);

}

}

字段的反射:

使用到的ReflectPoint

publicclassReflectPoint {

   privateintx;

   publicinty;

   public ReflectPoint(int x, int y) {

      super();

      this.x = x;

      this.y = y;

  

}

publicclassReflectDemo2 {

 

   publicstaticvoidmain(String[] args) throws Exception {

ReflectPoint rp = newReflectPoint(3,5);

      FieldfieldY = rp.getClass().getField("y");

      System.out.println(fieldY.get(rp));

     

      Fieldfieldx = rp.getClass().getDeclaredField("x");

      fieldx.setAccessible(true);

      System.out.println(fieldx.get(rp));

}

}

 

反射成員變量的綜合案例:

publicclassReflectPoint {

   privateintx;

   publicinty;

   public String str1 = "ball";

   public String str2 = "basketball";

   public String str3 = "itcast";

 

   public ReflectPoint(int x, int y) {

      super();

      this.x = x;

      this.y = y;

   }

 

   //@Override可以判斷重載的方法是否寫正確

   @Override

   public String toString(){

      return"ReflectPoint [x="+ x + ", y=" + y + ", str1="+ str1

           +", str2="+ str2+ ", str3="+ str3+ "]";

   }

  

}

 

 

publicclassReflectDemo2 {

 

   publicstaticvoidmain(String[] args) throws Exception {

      //操作field字段

      changeStringValue(rp);

      System.out.println(rp);

}

 

privatestaticvoidchangeStringValue(Object obj) throwsException {

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

      for(Field field : fields) {

         //比較同一份字節碼使用==而不是使用equals

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

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

           StringnewValue = value.replace('b', 'a');

           field.set(obj,newValue);

         }

      }

   }

}

 

反射得到類的方法:

methodCharAt.invoke(null, 1)當第一個參數爲null時,意味着調用的是靜態的方法

//jdk1.4的語法來調用

System.out.println(methodCharAt.invoke(str1,newObject[] {2}));

//jdk1.5的語法來調用

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

publicclassReflectDemo1 {

   publicstaticvoidmain(String[] args) throws Exception {

      Stringstr1 = "abc";

      //得到類的方法,String.charAt方法

      MethodmethodCharAt = String.class.getMethod("charAt", int.class);

   //methodCharAt.invoke(null,1)當第一個參數爲null時,意味着調用的是靜態的方法

      System.out.println(methodCharAt.invoke(str1,1));//jdk1.5的語法來調用

System.out.println(methodCharAt.invoke(str1,newObject[] {2}));//jdk1.4的語法來調用

 

}

}

 

 

反射執行某個類中的main方法:

對接收數組參數的成員方法進行反射

 

方法一:     mainMethod.invoke(null, new Object[]{new String[] {"111","222","333"}});

方法二:     mainMethod.invoke(null, (Object)newString[]{"111","222","333"});

 

 

publicclassReflectDemo1 {

 

   publicstaticvoidmain(String[] args) throws Exception {

//反射執行某個類中的main方法

      StringstartingClassName = args[0];

      MethodmainMethod =Class.forName(startingClassName).getMethod("main", String[].class);

      mainMethod.invoke(null, new Object[]{new String[] {"111","222","333"}});

      mainMethod.invoke(null, (Object)new String[] {"111","222","333"});

         }

}

 

classTestArguments {

   publicstaticvoidmain(String[] args) {

      for(String s : args) {

         System.out.println(s);

      }

   }

}

 

注意在運行的時候要傳遞TestArguments類的包給ReflectDemo1

 

數組的反射:

publicclassReflectDemo1 {

 

   publicstaticvoidmain(String[] args) throws Exception {

int[]a1 =newint[3];

      int[] a2 = newint[4];

      int[][] a3 = newint[2][3];

      String[] a4 = new String[] {"abc","bcd","cde"};

      System.out.println(a1.getClass()== a2.getClass());

//    System.out.println(a1.getClass()== a4.getClass());

//    System.out.println(a1.getClass()== a3.getClass());

      System.out.println(a1.getClass().getName());

      System.out.println(a1.getClass().getSuperclass().getName());

      System.out.println(a4.getClass().getSuperclass().getName());

     

      Object aObj1 = a1;

      Object aObj2 = a4;

//    Object[] aObj3= a1;

      Object[] aObj4 = a3;

      Object[] aObj5 = a4;

     

      System.out.println(a1);

      System.out.println(a4);

      System.out.println(Arrays.asList(a1));

      System.out.println(Arrays.asList(a4));

 

}

}

 

數組的反射應用:

publicclassReflectDemo1 {

 

   publicstaticvoidmain(String[] args) throws Exception {

String[] a4 = newString[]{"abc","bcd","cde"};

      printObject(a4);

      printObject("xyz");

   }

 

     privatestaticvoidprintObject(Object obj) {

      Classclazz = obj.getClass();

      if(clazz.isArray()) {

         int len = Array.getLength(obj);

         for(int i = 0; i < len; i++){

           System.out.println(Array.get(obj,i));

         }

      }else{

         System.out.println(obj);

      }

   }

}

 

 

 

反射的綜合案例:

ArrayList_HashSet的比較以及HashCode的分析

 

ArrayList是線性的存放,有多少放多少,按照先後的順序

HashSet是存放不重複的,存放之前先判斷集合中是否存在,不存在才放入

HashCode是一種編碼方式,在Java中,每個對象都會有一個hashcode,Java可以通過這個hashcode來識別一個對象

publicclassReflectDemo2 {

 

   publicstaticvoidmain(String[] args) {

      Collectioncollection= newHashSet();

      ReflectPointpt1 = newReflectPoint(3, 3);

      ReflectPointpt2 = newReflectPoint(5, 5);

      ReflectPointpt3 = newReflectPoint(3, 3);

     

      collection.add(pt1);

      collection.add(pt2);

      collection.add(pt3);

      collection.add(pt1);

     

/*

*此處並不能移走pt1,因爲將數據加入hashset中以後不能再去更改他,

這樣會導致內存泄露

 

內存泄露的作用,此處是一個例子,java中有內存泄露嗎?爲什麼?

      pt1.y= 7;

      collection.remove(pt1);

      */

      System.out.println(collection.size());

     

   }

 

}

 

packagecom.wj.reflect;

 

publicclassReflectPoint {

   privateintx;

   publicinty;

   public ReflectPoint(int x, int y) {

      super();

      this.x = x;

      this.y = y;

   }

 

   @Override

   publicint hashCode() {

      finalint prime = 31;

      int result = 1;

      result= prime * result + x;

      result= prime * result + y;

      return result;

   }

 

   @Override

   publicbooleanequals(Object obj) {

      if (this == obj)

         returntrue;

      if (obj == null)

         returnfalse;

      if (getClass() !=obj.getClass())

         returnfalse;

      ReflectPointother = (ReflectPoint) obj;

      if (x != other.x)

         returnfalse;

      if (y != other.y)

         returnfalse;

      returntrue;

   }

 

   @Override

   public String toString(){

      return"ReflectPoint [x="+ x + ", y=" + y + ", str1="+ str1

           +", str2="+ str2+ ", str3="+ str3+ "]";

   }

  

}

用類加載器管理資源和配置文件,也會使用到反射。詳見另一篇博客

 

 

發佈了29 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章