java反射 實例


首先介紹幾個概念:

      1、Java反射的概念
  反射含義:可以獲取正在運行的Java對象。
  2、Java反射的功能
  1)可以判斷運行時對象所屬的類
  2)可以判斷運行時對象所具有的成員變量和方法
  3)通過反射甚至可以調用到private的方法
  4)生成動態代理
  3、實現Java反射的類
  1)Class:它表示正在運行的Java應用程序中的類和接口
  2)Field:提供有關類或接口的屬性信息,以及對它的動態訪問權限
  3)Constructor:提供關於類的單個構造方法的信息以及對它的訪問權限
  4)Method:提供關於類或接口中某個方法信息
  注意:Class類是Java反射中最重要的一個功能類,所有獲取對象的信息(包括:方法/屬性/構造方法/訪問權限)都需要它來實現
  4、編寫Java反射程序的步驟:

  1)必須首先獲取一個類的Class對象
  例如:
  Class c1 = Test.class;
  Class c2 = Class.forName(“com.reflection.Test”);
  Class c3 = new Test().getClass();
  2)然后分別調用Class對象中的方法來獲取一個類的屬性/方法/構造方法的結構
  注意:如果要能夠正常的獲取類中方法/屬性/構造方法應該重點掌握如下的反射類
  Field
  Constructor
  Method

原理講的比較清楚的 推薦這個文章 http://www.cnblogs.com/gulvzhe/archive/2012/01/27/2330001.html

 

下面的例子演示通過反射給變量賦值

 1 package org.tianchi.userItem;
 2 
 3 import java.lang.reflect.Field;
 4 
 5 public class PrivateTest {     
 6     private String name = "hello";     
 7     public  long number ;
 8 
 9     public String getName() {     
10         return name;     
11     }    
12     
13     public void setName(String name) {
14         this.name = name;
15     }
16 
17     public static void main(String[] args) throws Exception {
18         PrivateTest pt = new PrivateTest();     
19         
20         Class<PrivateTest> clazz = PrivateTest.class;     
21              
22         Field field = clazz.getDeclaredField("name");     
23         field.setAccessible(true);     
24         field.set(pt, "world");     
25         field.setAccessible(false);    
26         
27         Field fieldNum = clazz.getDeclaredField("number");     
28         fieldNum.setAccessible(true);     
29         fieldNum.set(pt, 20);     
30         fieldNum.setAccessible(false);  
31              
32         System.out.println(pt.getName());
33         System.out.println(pt.number);
34     }
35 }
View Code

 

2、 利用反射創建一個無法通過new實例化的類的實例,並調用其私有方法進行數據傳遞(此為轉載http://www.cnblogs.com/pricks/archive/2009/08/11/1543855.html)

 1 首先創建一個無法實例化的類:Customer.java:
 2 public class Customer {
 3     private long id;
 4     private String name;
 5     private String age;
 6     
 7     private static Customer instance = null;
 8     /** 顯示將構造函數聲明為私有,外界無法通過new來實例化本類 */
 9     private Customer(){}
10     private static synchronized Customer getInstance(){
11         if(instance == null){
12             return new Customer();
13         }
14         return instance;
15     }
16     
17     /** 本set()方法為私有方法,外界無法直接為id屬性賦值 */
18     private void setId(long id) {
19         this.id = id;
20     }
21     public long getId() {
22         return id;
23     }
24     /** 本set()方法為私有方法,外界無法直接為name屬性賦值 */
25     private void setName(String name) {
26         this.name = name;
27     }
28     public String getName() {
29         return name;
30     }
31     /** 本set()方法為私有方法,外界無法直接為age屬性賦值 */
32     private void setAge(String age) {
33         this.age = age;
34     }
35     public String getAge() {
36         return age;
37     }
38 }
39 
40 接下來,開始利用反射創建該類實例,並調用其私有化方法來為其屬性賦值,最后調用其公開的方法驗證其屬性是否被賦上了值:
41 import java.lang.reflect.Field;
42 import java.lang.reflect.Method;
43 
44 public class test {
45     public static void main(String[] args) {
46    //創建類的實例
47      java.lang.Class c = null;
48         Customer customer = null;
49         try{
50             c = Customer.class;
51             Method m1 = c.getDeclaredMethod("getInstance");
52             m1.setAccessible(true);//這句至關重要,不設置為true,便無法獲取私有方法
53             customer = (Customer)m1.invoke(c);
54         } catch(Exception e){}
55         
56         try{
57             java.lang.reflect.Field fieldId = customer.getClass().getDeclaredField("id");//獲取私有成員變量id
58             
59             //獲取私有方法setId(int id)
60             String firstLetter = fieldId.getName().substring(0, 1).toUpperCase();
61             String setName = "set" + firstLetter + fieldId.getName().substring(1);
62             String getName = "get" + firstLetter + fieldId.getName().substring(1);
63             java.lang.reflect.Method setMethod = customer.getClass().getDeclaredMethod(setName, new Class[]{fieldId.getType()});
64             Method getMethod = customer.getClass().getDeclaredMethod(getName, new Class[]{});
65             setMethod.setAccessible(true);//使私有方法可以被獲取到
66             setMethod.invoke(customer, new Object[]{ 23 });//調用該私有方法並傳遞數據
67             
68             System.out.println("-------------通過公共方法獲取到的id值:" + customer.getId());
69             System.out.println("-------------通過反射獲取到的id值:" + getMethod.invoke(customer, null));
70             
71             //下面將模仿上面的這一段代碼,通過反射來分別為name和age這兩個私有成員變量賦值
72             Field fieldName = customer.getClass().getDeclaredField("name");
73             firstLetter = fieldName.getName().substring(0, 1).toUpperCase();
74             setName = "set" + firstLetter + fieldName.getName().substring(1);
75             setMethod = customer.getClass().getDeclaredMethod(setName, new Class[]{ fieldName.getType() });
76             setMethod.setAccessible(true);
77             setMethod.invoke(customer, "張三");
78             System.out.println("-----------------姓名:" + customer.getName());
79             
80             Field fieldAge = customer.getClass().getDeclaredField("age");
81             firstLetter = fieldAge.getName().substring(0, 1).toUpperCase();
82             setName = "set" + firstLetter + fieldAge.getName().substring(1);
83             setMethod = customer.getClass().getDeclaredMethod(setName, new Class[]{ fieldAge.getType() });
84             setMethod.setAccessible(true);
85             setMethod.invoke(customer, "40");
86             System.out.println("-----------------年齡:" + customer.getAge());
87         } catch(Exception e){}
88     }
89 }
View Code

 

這里需要注意:java.lang.reflect.Method貌似是值對象,如果將其傳遞到另一個方法中並做處理,然后從那個方法中出來后,依然保持其原來的屬性不變,沒有一點引用類型對象的特征。
  同時,這里的Customer類雖然使用了一個單例模式,但如果我們使用反射的方法來實例化兩個該對象實例,它們並非指向同一個引用,例如:
  private static Customer test1(){
        java.lang.Class c = null;
        Customer customer = null;
        try{
            c = Customer.class;
            Method m1 = c.getDeclaredMethod("getInstance");
            m1.setAccessible(true);//這句至關重要,不設置為true,便無法獲取私有方法
            customer = (Customer)m1.invoke(c);
        } catch(Exception e){}
  }
  public static void main(String[] args) {
        Customer c1 = test1();
        Customer c2 = test1();
        System.out.println("-----------------------" + c1.equals(c2));
        System.out.println("-----------------------" + (c1 == c2));
    }
  編譯后,兩個都顯示為false。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM