深入java反射

反射的基石——Class類
Java程序中的各個Java類屬於同一類事物,描述這類事物的Java類名就是Class。比如:衆多的人可以用一個Person類來表示,而這個類就可以描述人的信息(姓名、年齡、性別等等),而衆多的Java類就可以用Class來表示。
   Question:Person類代表人,它的實例對象可以是張三、李四,Class類代表Java類,它的各個實例對象有分別代表什麼呢?
   Answer:  對應各個類在內存中的字節碼。一個類被類加載器加載到內存中,佔用一份存儲空間,這個空間裏面的內容就是類的字節碼,不同的類的字節碼是不同的,所以它們在內存中的內容是不同的,這一個個空間可分別用一個個的對象來表示,這些對象顯然具有相同的類型,即Class類型。

如何得到各個字節碼對應的實例對象,有三種方法:
   1、類名.class,例如:System.class
   2、對象.getClass(),例如:new Data().getClass()
   3、Class.forName("類名"),例如:Class.forName("java.util.Date")

Class類的屬性和方法請參見jdk

 

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

 

Contructor類
  1、得到某個類的所有構造方法:
     Contructor[] contructors = lass.forName("類名").getContructors();
  2、得到某個特定的構造方法:
     //獲得方法時要用到類型
     Contructor contructors = Class.forName("類名").getContructor(參數類型.class,...);
  3、創建實例對象
     通常方式:String str = new String(new StringBuffer("abc"));
     //調用獲得的方法時要用到上面相同類型的實例
     反射方式:String str = (String)contructor.newInstance(new StringBuffer("abc"));
  4、Class.forName();
     ·示例:String obj = (String)Class.forName("java.lang.String").newInstence();
     ·該方法內部先得到默認的構造方法,然後用該構造方法創建實例
     ·該方法的內部具體代碼是怎樣的呢?用到了緩存機制來保存默認構造方法的對象
   
Field類
  Filed類代表某個類中的成員變量 
  示例:
     RefletPoint.java
      private int x;
 
      public int y;
 
      public ReflectPoint() {}
 
      public ReflectPoint(int x,int y) {
            this.x = x;
            this.y = y;
      }

 

      FieldTest.java
      ReflectPoint p1 = new ReflectPoint(2,8);
      Field fy = Class.forName("com.zouc.reflect.ReflectPoint").getField("y");
      System.out.println(fy.get(p1));;   //8
  
      Field fx = Class.forName("com.zouc.reflect.ReflectPoint").getDeclaredField("x");
      fx.setAccessible(true);
      System.out.println(fx.get(p1));   //2

      Question: 得到的Field對象是對應於類上的成員變量?還是對應到對象上的成語變量?
      Anwser:是類上的成員變量。因爲對象可以有多個,而類只有一個,所以fx.fy是得到的類上的那一份字節碼。
  
Method類
   Method類代表某個類中一個成員方法
   ·得到類中的某個方法
        例子:Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
   ·調用方法:
        通常方式:str.charAt(1);
        反射方式:charAt.invoke(str,1);
   注意:如果傳遞給Method對象的invoke()方法的第一個參數是null,這說明該Method對象對應的是一個靜態方法
   示例:  對接收數組參數的成員方法進行反射
        package com.zouc.reflect;

        import java.lang.reflect.InvocationTargetException;
        import java.lang.reflect.Method;

        public class Test {

             public static void main(String[] args) throws SecurityException,   NoSuchMethodException,               ClassNotFoundException, IllegalArgumentException,    IllegalAccessException, InvocationTargetException {
                    String startingClassName = args[0];
                    Method mainMethod = Class.forName(startingClassName).getMethod("main",    String[].class);
                    mainMethod.invoke(null, (Object)new String[]{"abc","def","xyz"});
              }
 
       }

 

        class Argumenmts {
               public static void main(String[] args) {
                      for(String arg : args) {
                            System.out.println(arg);
                    }
              }
        }

 

數組的反射
   ·具有相同維數和元素類型的數組屬於同一個類型,即具有相同的Class實例對象
   ·代表數組的Class實例對象的getSuperclass()方法返回的父類爲Object類對應的Class
   ·基本類型的一維數組可以當做Ojbect類型使用,不能當做Object[]類型使用,而二維數組可以當做     Object類型使用,也可以當做Object[]類型使用
   示例:
        int[] a = new int[3];
        int[] b = new int[4];
        int[][] c = new int[3][4];
        String[] s = new String[5];
  
        System.out.println(a.getClass() == b.getClass());  //true
        System.out.println(a.getClass() == c.getClass());  //false
        System.out.println(c.getClass() == s.getClass());  //false
     ·Array工具類用於完成對數組的反射操作
         public static void printObject(Object obj) {
                Class obyte = obj.getClass();
                if (obyte.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);
              }
          }

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