2014-10-08 110 views
0

我想知道如何使用我的JUnit測試反射來訪問私有內部類的私有字段。使用反射訪問私人內部類字段

這裏是什麼,我需要一個例子:

public class A 
{ 
    private Map<Integer, InnerClass> objectMap = new TreeMap<Integer, InnerClass>.descendingMap(); 

    private class InnerClass  
    { 
     private int fieldOne 
     private int fieldTwo 
    } 
} 

在這個例子中,我希望訪問在

我已經試過了A的實例fieldOne和fieldTwo的值以下:

A instanceA = new A(); 

Field privateObjectMapField = A.class.getDeclaredField("objectMap"); 
privateObjectMapField.setAccessible(true); 
NavigableMap<Integer, Class<?>> fieldValue = (NavigableMap<Integer, Class<?>>) privateObjectMapField.get(instanceA); 

// 5 is a key in the map so this should set declaredClass to an instance of InnerClass 
Class<?> declaredClass = fieldValue.get(5).getClass(); 
Field fieldOne = declaredClass.getDeclaredField("fieldOne"); 
fieldOne.setAccessible(true); 
Assert.assertEquals(100, fieldOne.getInt(declaredClass)); 

在這種情況下,它crashses在:Class<?> declaredClass = fieldValue.get(5).getClass(); 出現錯誤:

java.lang.ClassCastException: com.test.A$InnerClass cannot be cast to java.lang.Class

有沒有人知道這裏有什麼問題?

我希望這個例子很清楚。

感謝

回答

0

應該

NavigableMap<Integer, InnerClass> fieldValue = (NavigableMap<Integer, InnerClass>) privateObjectMapField.get(instanceA); 
+0

InnerClass是私人的,所以我的JUnit類無法看到它 – sam 2014-10-08 21:59:38

+0

所以也許你必須改變你的類結構,因爲在這個例子中,InnerClass不能被測試/達到。 – ToYonos 2014-10-08 22:01:40

0

簡短的回答:

objectMapMap<Integer, A.InnerClass>,並且如果它是一個Map<Integer, Class<?>>你對待它。

試試這個,而是:

NavigableMap<Integer, ?> fieldValue = ... 

詳細的解答(你應該閱讀,如果你想了解泛型瞭解這一點)

fieldValue方法聲明爲NavigableMap<Integer, Class<?>>,這意味着即:

fieldValue.get(5) 

只是將這樣的:

((Class<?>) fieldValue.get(5)) 

這是因爲如何erasure作品。基本上,declaredClass不是真的是 a NavigableMap<Integer, Class<?>>,它只是一個NavigableMap(這是它的「原始類型」),編譯器可以向其添加類型檢查和自動投射。

那麼,如果在關鍵5的對象不是真的Class會發生什麼?當你嘗試轉換它時,你會得到一個ClassCastException。這就是你正在發生的事情,因爲關鍵5的對象是A.InnerClass,而不是Class。它基本上沒有什麼不同:

Object o = new InnerClass(); 
Class<?> boom = (Class<?>) o; // ClassCastException 

至於修復,這取決於你實際上正在嘗試做什麼。如果僅用於測試,則可以考慮使InnerClass具有默認可見性(又名包私有)而不是私有。您也可以檢索objectMap作爲Map<Integer, ?>,然後致電fieldValue.get(5).getClass()。這將得到關鍵的5的對象,碰巧是InnerClass(但你不需要在編譯時指定它),然後調用Object.getClass()來獲得它的類。

+0

感謝您的信息。但我仍然有問題。 我有這個: 'NavigableMap fieldValue =(NavigableMap )privateObjectMapField.get(instanceA); 類 declaredClass = fieldValue.get(5).getClass(); FieldOne = declaredClass.getDeclaredField(「fieldOne」); fieldOne.setAccessible(true); Assert.assertEquals(100,fieldOne.getInt(declaredClass)); ' 這一次它調用getInt失敗: '不能設置INT場com.test.A $ InnerClass.fieldOne到java.lang.Class' 是否應宣告類仍然是類在這裏? – sam 2014-10-08 22:18:59

+0

聽起來像是一個新問題 - 很難閱讀如此多的代碼,使其成爲評論。但我鼓勵你嘗試挑選每一步並自行調試,並用對泛型工作原理的新理解武裝起來。 :) – yshavit 2014-10-08 23:56:05