首先介紹幾個概念:
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 }
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 }
這里需要注意: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。