跳轉到內容

使用反射訪問私有特性

50% developed
來自 Wikibooks,開放的書籍,為開放的世界

瀏覽反射主題:v  d  e )

可以透過反射獲取類的所有特性,包括訪問private方法和變數。但並不總是如此,請參閱[1]。讓我們看以下示例

Computer code 程式碼清單 10.3:Secret.java
public class Secret {
  private String secretCode = "It's a secret";
 
  private String getSecretCode() {
    return secretCode;     
  }
}

儘管欄位和方法被標記為private,但以下類表明可以訪問類的private特性

Computer code 程式碼清單 10.4:Hacker.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class Hacker {
 
   private static final Object[] EMPTY = {};
 
   public void reflect() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
     Secret instance = new Secret();
     Class<?> secretClass = instance.getClass();
 
     // Print all the method names & execution result
     Method methods[] = secretClass.getDeclaredMethods();
     System.out.println("Access all the methods");
     for (Method method : methods) {
        System.out.println("Method Name: " + method.getName());
        System.out.println("Return type: " + method.getReturnType());
        method.setAccessible(true);
        System.out.println(method.invoke(instance, EMPTY) + "\n");
     }
 
     // Print all the field names & values
     Field fields[] = secretClass.getDeclaredFields();
     System.out.println("Access all the fields");
     for (Field field : fields) {
        System.out.println("Field Name: " + field.getName());
        field.setAccessible(true);
        System.out.println(field.get(instance) + "\n");
     }
  }
 
  public static void main(String[] args) {
    Hacker newHacker = new Hacker();
 
    try {
      newHacker.reflect();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
Standard input or output 程式碼清單 10.4 的控制檯
Access all the methods
Method Name: getSecretCode
Return type: class java.lang.String
It's a secret
Access all the fields
Field Name: secretCode
It's a secret
Clipboard

待辦事項
我們需要新增一些關於這裡發生了什麼的解釋。


JUnit - 測試私有方法

[編輯 | 編輯原始碼]

JUnit 是單元測試用例,用於測試 Java 程式。現在您知道如何在 JUnit 中使用反射來測試私有方法。關於測試私有成員是否是一種好習慣存在長期爭論[1];在某些情況下,您希望確保一個類表現出正確的行為,而不會將需要檢查的欄位設定為公有(因為通常將建立訪問器僅僅為了單元測試被認為是不好的做法)。在其他情況下,您可以透過使用反射來測試所有較小的私有方法(以及它們的各種分支)來簡化測試用例,然後測試主函式。使用dp4j [失效連結],可以測試私有成員,而無需直接使用反射 API,只需像從測試方法訪問它們一樣訪問它們;dp4j 在編譯時注入所需的反射程式碼[2]

  1. 單元測試私有方法的最佳方法是什麼?,2011 年 3 月 7 日
  2. 編譯時注入的反射 API [失效連結]


Clipboard

待辦事項
新增一些類似於變數中練習的練習

華夏公益教科書