原文地址:http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html
===========================================================================================
儘管普遍的觀點是不能直接訪問私有欄位和私有方法的,實際上通過Java反射是可以訪問其他類的私有欄位和私有方法的。它甚至不是那麼困難。在單元測試期間很容易使用。本文將介紹你怎麼做。
注:這個只會作用在執行獨立的Java應用程式時,如寫單元測試和常規應用。如果你嘗試在Java Applet內使用它,你需要處理好SecurityManager。但是,因為這不是你經常要做的事情,所以在本文中將不會涉及它。
下面是本文的主題列表:
- Accessing Private Fields (訪問私有欄位)
- Accessing Private Methods (訪問私有方法)
===========================================================================================
- Accessing Private Fields
為了訪問私有欄位,你需要呼叫Class.getDeclaredField(String name)方法或者Class.getDeclaredFields()方法。Class.getField(String name)和Class.getFields()方法只會返回public的欄位,所有它們不會工作。下面是一個簡單的例子,通過Java反射去訪問一個類的私有欄位:
public class PrivateObject { private String privateString = null; public PrivateObject(String privateString) { this.privateString = privateString; } } PrivateObject privateObject = new PrivateObject("The Private Value"); Field privateStringField = PrivateObject.class.getDeclaredField("privateString"); privateStringField.setAccessible(true); String fieldValue = (String) privateStringField.get(privateObject); System.out.println("fieldValue = " + fieldValue);
這段程式碼示例將會列印出文字“fieldValue = The Private Value”,是PrivateObject例項在程式碼示例最開始賦值給私有欄位privateString的。
注意這裡使用的方法PrivateObject.class.getDeclaredField("privateString")。是這個方法呼叫返回了私有欄位的值。這個方法只會返回在給定類裡宣告的欄位的值,而不是其他任何在超類裡宣告的欄位的值。
注意字型加粗的一行。僅僅針對反射,通過呼叫Field.setAccessible(true)方法,關閉了對特定的Field例項的訪問檢查。現在你可以訪問它,儘管它是private,或者protected,或者是package scope,即使呼叫者不在這個範圍內。你仍然不能通過一般的程式碼去訪問這些欄位。編譯器不允許這樣幹。
===========================================================================================
- Accessing Private Methods
為了訪問私有方法,你需要呼叫Class.getDeclaredMethod(String name, Class[ ] parameterTypes)方法或者Class.getDeclaredMethods()方法。Class.getMethod(String name, Class[ ] parameterTypes)方法和Class.getMethods()只會返回共有的方法,所以它們不會工作。下面是一個簡單的程式碼示例,通過Java反射訪問一個類的私有方法:
public class PrivateObject { private String privateString = null; public PrivateObject(String privateString) { this.privateString = privateString; } private String getPrivateString(){ return this.privateString; } } PrivateObject privateObject = new PrivateObject("The Private Value"); Method privateStringMethod = PrivateObject.class.getDeclaredMethod("getPrivateString", null); privateStringMethod.setAccessible(true); String returnValue = (String) privateStringMethod.invoke(privateObject, null); System.out.println("returnValue = " + returnValue);
這段程式碼示例將會列印出文字“returnValue = The Private Value”,是在程式碼示例最開始建立的PrivateObject例項呼叫getPrivateString()方法時的返回值。
注意這裡使用的方法PrivateObject.class.getDeclaredMethod("privateString")。是這個方法呼叫返回的私有方法。這個方法只會返回在給定的類裡面宣告的方法,而不是在任何超類裡宣告的方法。
注意字型加粗的一行。僅僅針對反射,通過呼叫Method.setAccessible(true)方法,關閉了對特定的Method例項的訪問檢查。現在你可以訪問它了,儘管它是private,或者protected,或者package scope,即使呼叫者不在這個範圍內。你仍然不能通過一般的程式碼訪問這些方法。編譯器不允許這樣幹。
========================================================================================
- 目錄
這是一個本教程到目前為止涵蓋的主題列表:
- Java反射——引言
- Java反射——Class物件
- Java反射——建構函式
- Java反射——欄位
- Java反射——方法
- Java反射——Getter和Setter
- Java反射——私有欄位和私有方法
- Java反射——註解
- Java反射——泛型
- Java反射——陣列
- Java反射——動態代理
- Java反射——類的動態載入和重新載入
(敬請期待下一篇翻譯)