反射機制

什麼是反射:

反射是Java語言的一個特性,它允許程序在運行時來進行自我檢查並且對內部的成員進行操作。例如它允許一個java的類獲取他所有的成員變量和方法並且顯示出來。
java的反射機制的實現要藉助4個類:Class,Constructor,Field,Method 其中Class代表的是類對象,Constructor  類的構造器對象,Field  類的屬性對象,Method 

類的方法對象。通過這四個對象我們可以粗略的看到一個類的各個組成部分。

 

在正常情況下,必須知道一個類的完整路徑之後纔可以實例化對象,但是在java中也允許通過一個對象來找到其所在的類的信息,那麼這實際上就是Class類的功能。

[java] view plain copy
  1. package com.itmyhome;  
  2.   
  3. class A{  
  4.       
  5. }  
  6. public class T {  
  7.   
  8.     public static void main(String[] args) {  
  9.         // TODO Auto-generated method stub  
  10.         A a = new A();  
  11.         System.out.println(a.getClass().getName());  //com.itmyhome.A  
  12.     }  
  13.   
  14. }  


Object類的支持

在Object類中定義了以下的方法,此方法將被所有子類繼承:

public  final  Class getClass()

以上的方法返回值的類型是一個"Class"類,實際上此類是java反射的源頭,實際上所謂反射從程序的運行結果來看也很好理解,即:可以通過對象反射求出類的名稱。

Class類

Class本身表示一個類的本身,通過Class可以完整的得到一個類中的完整結構,包括此類中的方法定義,屬性定義等。

實例化Class類對象

有三種方法實例化Class對象:

第一種:通過forName()方法

第二種:類.class

第三種:對象.getClass()

[java] view plain copy
  1. package com.itmyhome;  
  2.   
  3. class A{  
  4.       
  5. }  
  6. public class T {  
  7.   
  8.     public static void main(String[] args) throws ClassNotFoundException {  
  9.         // TODO Auto-generated method stub  
  10.         Class<?> c1 = Class.forName("com.itmyhome.A");  
  11.         Class<?> c2 = A.class;  
  12.         Class<?> c3 = new A().getClass();  
  13.         System.out.println(c1.getName());  
  14.         System.out.println(c2.getName());  
  15.         System.out.println(c3.getName());  
  16.     }  
  17.   
  18. }  

 

Class主要是反射的源頭,不光可以取得對象所在類的信息,也可以直接通過Class類的方法進行對象的實例化操作正常情況下,使用關鍵字new爲對象實例化,如果現在已經實例化好了Class對象,則就可以通過Class類中提供的

實例化對象

[java] view plain copy
  1. package com.itmyhome;  
  2.   
  3. class Person {  
  4.     private String name;  
  5.     private int age;  
  6.       
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.     public void setName(String name) {  
  11.         this.name = name;  
  12.     }  
  13.     public int getAge() {  
  14.         return age;  
  15.     }  
  16.     public void setAge(int age) {  
  17.         this.age = age;  
  18.     }  
  19.     public String toString() {  
  20.         // TODO Auto-generated method stub  
  21.         return "name: " + name + ",age: " + age;  
  22.     }  
  23. }  
  24.   
  25. public class T {  
  26.   
  27.     public static void main(String[] args) throws ClassNotFoundException {  
  28.         Class<?> c = Class.forName("com.itmyhome.Person");  
  29.         Person person = null;  
  30.         try {  
  31.             person = (Person) c.newInstance();  //實例化對象  
  32.         } catch (InstantiationException e) {  
  33.             e.printStackTrace();  
  34.         } catch (IllegalAccessException e) {  
  35.             e.printStackTrace();  
  36.         }  
  37.         person.setName("itmyhome");  
  38.         person.setAge(23);  
  39.         System.out.println(person);  
  40.     }  
  41.   
  42. }  


通過以上的代碼,可以發現,即使不使用關鍵字new對象也可以進行實例化操作,反射的作用。

但是,在使用以上操作的時候有一點必須注意,在操作中類中必須存在無參構造方法,否則無法實例化

報以下異常

[java] view plain copy
  1. java.lang.InstantiationException: com.itmyhome.Person  
  2.     at java.lang.Class.newInstance0(Class.java:340)  
  3.     at java.lang.Class.newInstance(Class.java:308)  
  4.     at com.itmyhome.T.main(T.java:35)  
  5. Exception in thread "main" java.lang.NullPointerException  
  6.     at com.itmyhome.T.main(T.java:41)  


對於以上的程序也並非沒有解決的方法,也是可以通過其他的方式進行實例化操作的,只是在操作的時候需要明確的調用類中的構造方法,並將參數傳遞進去之後纔可以進行實例化操作,操作步驟如下:

1、通過Class類中的getConstructors()取得本類中的全部構造方法。

2、向構造方法中傳遞一個對象數組進去,裏面包含了構造方法中所需的各個參數。

3、之後通過Constructor實例化對象。

[java] view plain copy
  1. package com.itmyhome;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4.   
  5. class Person {  
  6.     private String name;  
  7.     private int age;  
  8.       
  9.     public Person(String name,int age){  
  10.         this.name = name;  
  11.         this.age = age;  
  12.     }  
  13.     public String getName() {  
  14.         return name;  
  15.     }  
  16.     public void setName(String name) {  
  17.         this.name = name;  
  18.     }  
  19.     public int getAge() {  
  20.         return age;  
  21.     }  
  22.     public void setAge(int age) {  
  23.         this.age = age;  
  24.     }  
  25.     public String toString() {  
  26.         // TODO Auto-generated method stub  
  27.         return "name: " + name + ",age: " + age;  
  28.     }  
  29. }  
  30.   
  31. public class T {  
  32.   
  33.     public static void main(String[] args) throws ClassNotFoundException{  
  34.         Class<?> c = Class.forName("com.itmyhome.Person");  
  35.         Constructor<?> cons[] = c.getConstructors();  
  36.         Person person = null;  
  37.         try {  
  38.             person = (Person) cons[0].newInstance("itmyhome",23);  //實例化對象  
  39.         } catch (Exception e) {  
  40.             e.printStackTrace();  
  41.         }   
  42.         person.setName("itmyhome");  
  43.         person.setAge(23);  
  44.         System.out.println(person);  
  45.     }  
  46.   
  47. }  


反射機制的深入----取得類的結構

在實際開發中,以上的程序就是反射應用最多的地方,當然,反射機制所提供的功能遠不止如此,還可以通過反射得到一個類的完整結構,那麼這就要使用到java.lang.reflect包中的以下幾個類:

Constructor:表示類中的構造方法

Field:表示類中的屬性

Method:表示類中的方法

這三個類都是AccessibleObject類中的子類

[java] view plain copy
  1. package com.itmyhome;  
  2.   
  3. interface IPerson{  
  4.     public static final String NAME = "itmyhome";  
  5.     public String toSay();  
  6.     public String toEat(String name,int age);  
  7. }  
  8. class Person implements IPerson{  
  9.     private String name;  
  10.     private int age;  
  11.     public Person(){    //無參構造  
  12.           
  13.     }  
  14.     public Person(String name,int age){  
  15.         this.name = name;  
  16.         this.age = age;  
  17.     }  
  18.     @Override  
  19.     public String toSay() {  
  20.         return "hello!";  
  21.     }  
  22.       
  23.     @Override  
  24.     public String toEat(String name, int age) {  
  25.         return "name: "+name+",age: "+age;  
  26.     }  
  27.     public String getName() {  
  28.         return name;  
  29.     }  
  30.     public void setName(String name) {  
  31.         this.name = name;  
  32.     }  
  33.     public int getAge() {  
  34.         return age;  
  35.     }  
  36.     public void setAge(int age) {  
  37.         this.age = age;  
  38.     }  
  39. }  


取得類所實現的全部接口

要想取得一個類所實現的全部接口,則必須使用Class類中的getInterfaces()方法,此方法定義如下:

[java] view plain copy
  1. public Class[] getInterfaces()  


此方法返回一個Class類的對象數組,之後就可以直接利用Class類中的getName()方法輸出即可。

因爲一個類可以同時實現多個接口,所以在此處就以一個數組的形式返回實現的全部接口。

[java] view plain copy
  1. public class T {  
  2.     public static void main(String[] args) throws Exception{  
  3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //實例化對象  
  4.         Class<?> c[] = cl.getInterfaces();   //以數組形式返回實現的全部接口  
  5.         for (int i = 0; i < c.length; i++) {  
  6.             System.out.println(c[i].getName());   //輸出接口名稱  
  7.         }  
  8.     }  
  9. }  


取得類所繼承的父類

一個類可以實現多個接口,但是隻能繼承一個父類,所以如果要想取得一個類的父類,可以直接使用Class類中的getSuperClass()方法。此方法定義如下:

[java] view plain copy
  1. public Class<? super T> getSuperClass()  


此方法返回的是Class實例,和之前的得到接口一樣,可以通過getName()方法取得名次。

一個類只繼承一個父類,如果一個類中沒有明確的指明繼承哪個類,則肯定繼承的是Object類。

[java] view plain copy
  1. public class T {  
  2.     public static void main(String[] args) throws Exception{  
  3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //實例化對象  
  4.         Class<?> c = cl.getSuperclass();   //取得繼承父類  
  5.         System.out.println(c.getName());  
  6.     }  
  7. }  


取得類中的全部構造方法

[java] view plain copy
  1. public class T {  
  2.     public static void main(String[] args) throws Exception{  
  3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //實例化對象  
  4.         Constructor<?> c[] = cl.getConstructors();  
  5.         for (int i = 0; i < c.length; i++) {  
  6.             System.out.println(c[i]);  
  7.         }  
  8.     }  
  9. }  


取得類中的方法

要想取得一個類中的全部方法,可以使用Class類中的getDeclaredMethods()方法,此方法返回一個Method類的對象數組,而如果要想進一步取得方法的具體信息,例如:方法的參數,拋出的異常等等,則就必須依靠Method類

public  Method[]  getDeclaredMethods()      輸出本類中的全部方法

public  Method[]  getMethods()  輸出全部的方法

[java] view plain copy
  1. public class T {  
  2.     public static void main(String[] args) throws Exception{  
  3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //實例化對象  
  4.         Method m1[] = cl.getMethods();  
  5.         for (int i = 0; i < m1.length; i++) {  
  6.             System.out.println(m1[i]);  
  7.         }  
  8.         System.out.println("*************");  
  9.         Method m2[] = cl.getDeclaredMethods();  
  10.         for (int i = 0; i < m2.length; i++) {  
  11.             System.out.println(m2[i]);  
  12.         }  
  13.     }  
  14. }  


取得類中的屬性

public  Field[]  getFields()    得到實現的接口和父類中的公共屬性

public  Field[]  getDeclaredFields()  得到本類中的全部屬性

以上方法返回的都是Field的數組,每一個Field對象就表示類中的一個屬性

[java] view plain copy
  1. public class T {  
  2.     public static void main(String[] args) throws Exception{  
  3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //實例化對象  
  4.         Field f1[] = cl.getFields();  
  5.         for (int i = 0; i < f1.length; i++) {  
  6.             System.out.println(f1[i]);  
  7.         }  
  8.         System.out.println("*********");  
  9.         Field f2[] = cl.getDeclaredFields();   //本類中的屬性  
  10.         for (int i = 0; i < f2.length; i++) {  
  11.             System.out.println(f2[i]);  
  12.         }  
  13.     }  
  14. }  

轉載出處: http://blog.csdn.net/itmyhome1990/article/details/8946220


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章