原文地址: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反射——類的動態加載和重新加載
(敬請期待下一篇翻譯)