天天看點

Java反射在類中的應用:通過反射通路成員變量

通過下列任意一個方法通路成員變量時将傳回 Field 類型的對象或數組。

  • getFields()
  • getField(String name)
  • getDeclaredFields()
  • getDeclaredField(String name)

上述方法傳回的 Field 對象代表一個成員變量。例如,要通路一個名稱為 price 的成員變量,示例代碼如下:

  1. objectgetDeciaredField("price");

Field類的常用方法如表 1 所示

表1 Field類的常用方法

方法名稱 說明
getName() 獲得該成員變量的名稱
getType() 擷取表示該成員變量的 Class 對象
get(Object obj) 獲得指定對象 obj 中成員變量的值,傳回值為 Object 類型
set(Object obj,Object value) 将指定對象 obj 中成員變量的值設定為 value
getlnt(0bject obj) 獲得指定對象 obj 中成員類型為 int 的成員變量的值
setlnt(0bject obj,int i) 将指定對象 obj 中成員變量的值設定為 i
setFloat(Object obj,float f) 将指定對象 obj 中成員變量的值設定為 f
getBoolean(Object obj) 獲得指定對象 obj 中成員類型為 boolean 的成員變量的值
setBoolean(Object obj,boolean b) 将指定對象 obj 中成員變量的值設定為 b
getFloat(Object obj) 獲得指定對象 obj 中成員類型為 float 的成員變量的值
setAccessible(boolean flag) 此方法可以設定是否忽略權限直接通路 private 等私有權限的成員變量
getModifiers() 獲得可以解析出該方法所采用修飾符的整數

例 1

下面通過一個案例來示範如何調用 Field 類的方法擷取動态類中各個成員的資訊。

(1) 首先建立一個 Book2 類,在該類中依次聲明一個 String、int、float 和 boolean 類型的成員,并設定不同的通路作用域。Book2 類最終的代碼如下:

  1. package ch12;
  2. public class Book2
  3. {
  4. String name;
  5. public int id;
  6. private float price;
  7. protected boolean isLoan;
  8. }

(2) 編寫測試類 Test03,在該類的 main() 方法中通過反射通路 Book2 類中的所有成員,并将該成員的名稱和類型資訊輸出到控制台。

Test03 類的代碼如下:

  1. package ch12;
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.Field;
  4. public class Test03
  5. {
  6. public static void main(String[] args)
  7. {
  8. Book2 book=new Book2();
  9. //擷取動态類Book2
  10. Class class1=book.getClass();
  11. //擷取Book2類的所有成員
  12. Field[] declaredFields=class1.getDeclaredFields();
  13. //周遊所有的成員
  14. for(int i=0;i<declaredFields.length;i++)
  15. { //擷取類中的成員變量
  16. Field field=declaredFields[i];
  17. System.out.println("成員名稱為:"+field.getName());
  18. Class fieldType=field.getType();
  19. System.out.println("成員類型為:"+fieldType);
  20. boolean isTurn=true;
  21. while(isTurn)
  22. {
  23. try
  24. { //如果該成員變量的通路權限為private,則抛出異常
  25. isTurn=false;
  26. System.out.println("修改前成員的值為:"+field.get(book));
  27. //判斷成員類型是否為int
  28. if(fieldType.equals(int.class))
  29. {
  30. System.out.println("利用setInt()方法修改成員的值");
  31. field.setInt(book, 100);
  32. }
  33. else if(fieldType.equals(float.class))
  34. { //判斷成員變量類型是否為float
  35. System.out.println("利用setFloat()方法修改成員的值");
  36. field.setFloat(book, 29.815f);
  37. }
  38. else if(fieldType.equals(boolean.class))
  39. { //判斷成員變量是否為boolean
  40. System.out.println("利用setBoolean()方法修改成員的值");
  41. field.setBoolean(book, true);
  42. }
  43. else
  44. {
  45. System.out.println("利用set()方法修改成員的值");
  46. field.set(book, "Java程式設計");
  47. }
  48. System.out.println("修改後成員的值為:" + field.get(book));
  49. } catch (Exception e)
  50. {
  51. System.out.println("在設定成員變量值時抛出異常,下面執行setAccessible()方法");
  52. field.setAccessible(true);
  53. isTurn=true;
  54. }
  55. }
  56. System.out.println("=============================\n");
  57. }
  58. }
  59. }

(3) 運作測試類 Test03,程式将會依次動态通路 Book2 類中的所有成員。通路 name 成員的運作效果如下所示:

成員名稱為:name
成員類型為:class java.lang.String
修改前成員的值為:null
利用set()方法修改成員的值
修改後成員的值為:Java程式設計
=============================      

通路 id 成員的運作效果如下所示:

成員名稱為:id
成員類型為:int
修改前成員的值為:0
利用setInt()方法修改成員的值
修改後成員的值為:100
=============================      

通路 price 成員的運作效果如下所示:

成員名稱為:price
成員類型為:float
在設定成員變量值時抛出異常,下面執行setAccessible()方法
修改前成員的值為:0.0
利用setFloat()方法修改成員的值
修改後成員的值為:29.815
=============================      

通路 isLoan 成員的運作效果如下所示:

成員名稱為:isLoan
成員類型為:boolean
修改前成員的值為:false
利用setBoolean()方法修改成員的值
修改後成員的值為:true
=============================