java中的反射機制詳解

來源:互聯網
上載者:User

  在Java運行時環境中,對於任意一個類,能否知道這個類有哪些屬性和方法?對於任意一個對象,能否調用它的任意一個方法?答案是肯定的。這種動態擷取類的資訊,以及動態調用對象的方法的功能來自於Java語言的反射(Reflection)機制。Java反射機制主要提供了以下功能:

       1.在運行時判斷任意一個對象所屬的類;
       2.在運行時構造任意一個類的對象;(在編譯時間通過new()方法就可以構造一個類的對象)
       3.在運行時判斷任意一個類所具有的成員變數和方法;
   4.在運行時調用任意一個對象的方法;
       5.產生動態代理。

  Reflection 是 Java 被視為動態(或准動態)語言的關鍵,允許程式於執行期利用Reflection APIs 取得任何已知名稱之 class 的內部資訊,包括 package、type、parameters、superclass、implemented interfaces、inner classes、 outer class、fields、constructors、methods、modifiers(如public,static等),並可於運行期產生instances、改變 fields 內容或調用methods(包括私人的方法,即通過反射我們可以打破類的封裝機制)。

  一般而言,開發人員社區說到動態語言,大致認同的一個定義是:“程式運行時,允許改變程式結構和變數類型,這種語言就稱為動態語言。”從這個觀點看,perl,python,ruby,javascript等是動態語言,c,c++,c#,java等都不是動態語言。

  儘管在這樣的定義與分類下,java並不是動態語言,但他卻有著一個非常突出的動態相關機制:Reflection。這個字的意思是“反射、映射、倒影”,用在java身上指的是我們可以於運行時載入、探知、使用編譯期間完全未知的classes。換句話說,Java程式可以載入一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並產生其對象實體、或對其fields設值、或調用其methods。這種“看透 class”的能力(the ability of the program to examine itself)被稱為introspection(內省、內觀、反省)。Reflection和introspection是常被並提的兩個術語。

  在JDK中,主要由以下類來實現Java反射機制,這些類都位於java.lang.reflect包中。

  •   Class類:代表一個類。(位於java.lang)
  •   Field類:代表類的成員變數(成員變數也稱為類的屬性)。
  •   Method類:代表類的方法。
  •   Constructor類:代表類的構造方法。
  •   Array類:提供了動態建立數組,以及訪問數組元素的靜態方法。
Field類:   提供有關類或介面的屬性的資訊,以及對它的動態存取權限。反射的欄位可能是一個類(靜態)屬性或執行個體屬性,簡單的理解可以把它看成一個封裝反射類的屬性的類。
Constructor類: 提供關於類的單個構造方法的資訊以及對它的存取權限。這個類和Field類不同,Field類封裝了反射類的屬性,而Constructor類則封裝了反射類的構造方法。
Method類: 提供關於類或介面上單獨某個方法的資訊。所反映的方法可能是類方法或執行個體方法(包括抽象方法)。 這個類不難理解,它是用來封裝反射類方法的一個類。
Class類: 類的執行個體表示正在啟動並執行 Java 應用程式中的類和介面。枚舉是一種類,注釋是一種介面。每個數組屬於被映射為 Class 對象的一個類,所有具有相同元素類型和維數的數組都共用該 Class 對象。
Object類: 每個類都使用 Object 作為超類。所有對象(包括數組)都實現這個類的方法。

  在java中,無論產生某個類的多少個對象,這些對象都對應於同一個class對象。 

  要想使用反射,首先要獲得對應類或對象的Class對象,擷取某個類或對象的Class對象的三種方法:
  1. 使用Class類的靜態方法:Class<?> classType = Class.forName("java.lang.String");
  2. 使用的.class文法:Class<?> classType = String.class;
  3. 適用對象的getClass()方法:String s = "aa"; Class<?> classType = s.getClass();

  若想通過反射來產生類的對象,有以下兩種方式:
  1. 先產生欲產生對象對應的Class對象,然後通過Class對象的newInstance()方法直接產生新的執行個體對象:
      Class<?> classType = String.class;
      String str = classType.newInstance();
  2. 先產生欲產生對象對應的Class對象,然後通過Class對象的getConstructor()方法產生構造方法對象,再通過該構造方法對象來產生新的執行個體對象:
      Class<?> classType = String.class;
    Constructor<?> constructor = classType.getConstructor();
      String str = constructor.newInstance();
 
  其中後者可以通過給getConstructor()方法傳遞參數而指定特定的構造方法(前者只能使用預設的即參數為空白的構造方法):
    Class<?> classType = object.getClass();
    Constructor<?> constructor = classType.getConstructor(new Class[]{String.class, int.class});
    Object obj = constructor.newInstance(new Object[]{"tom", 23});

  

 1 import java.lang.reflect.Field; 2 import java.lang.reflect.Method; 3  4  5 public class ReflectTest { 6     public Object copy (Object object) throws Exception{ 7         Class<?> classType = object.getClass(); 8         Object objectCopy = classType.getConstructor(new Class[]{}) 9             .newInstance(new Object[]{});10         Field[] fields = classType.getDeclaredFields();11         for(Field field: fields) {12             String name = field.getName();13             String firstLetter = name.substring(0, 1).toUpperCase();14             String setMethodName = "set" + firstLetter + name.substring(1);15             String getMethodName = "get" + firstLetter + name.substring(1);16             Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});17             Method getMethod = classType.getMethod(getMethodName, new Class[]{});18             setMethod.invoke(objectCopy, new Object[]{getMethod.invoke(object, new Object[]{})});            19         }20         return objectCopy;21     }    22     23     public static void main(String[] args) throws Exception{24         Customer customer = new Customer("Tom", 23);25         customer.setId(1L);26         ReflectTest reflectTest = new ReflectTest();27         Customer customer2 = (Customer)reflectTest.copy(customer);28         System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge());29     }30 }31 32 class Customer {33     private Long id;34     private String name;35     private int age;36     37     public Customer() {38     }39     40     public Customer(String name, int age) {41         this.name = name;42         this.age = age;43     }44 45     public Long getId() {46         return id;47     }48 49     public void setId(Long id) {50         this.id = id;51     }52 53     public String getName() {54         return name;55     }56 57     public void setName(String name) {58         this.name = name;59     }60 61     public int getAge() {62         return age;63     }64 65     public void setAge(int age) {66         this.age = age;67     }68 }

  

 

  

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.