2016-07-05 16 views
0

私はそれが悪いコード設計である知っているがネストされている値にアクセスするには、しかし、一時的なハックとして...リフレクションは、クラス

私は値が静的な入れ子になったクラスの初期化されている民間のマップにアクセスする必要があります。次の例では、別のパッケージからmyMapの各値にアクセスしたいとします。

package belongs.to.someone.else 

public class SOExample { 
    private Map<String, NestedClass> myMap; 

    static class NestedClass { 
     final int data; 
     NestedClass(final int data) { 
      this.data = data; 
     } 
    } 

    public void populateMyMap(){ 
     for(int i=0; i<100; i++){ 
      this.myMap.put(Integer.toString(i), new NestedClass(i)); 
     } 
    } 
} 

しかし、私はアクセス可能にSOExample.myMapフィールドを設定しようとしたとき鶏と卵の問題に遭遇しているようです。最後のステートメントのSOExample.NestedClass値の "パッケージの外部からアクセスできません"というエラーが表示されます。

package belongs.to.me 
public class SOExampleMyPackage { 
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 
     SOExample example = new SOExample(); 
     example.populateMyMap(); 

     // Make the example.myMap field accessible 
     Field f = example.getClass().getDeclaredField("myMap"); 
     f.setAccessible(true); 
     // Next line throws error 
     Map<String, SOExample.NestedClass> myMapHere = (Map<String, SOExample.NestedClass>) f.get(example); 
    } 
} 

この問題の解決方法に関するご意見をお待ちしております。

+0

「myMapHere」はどのように使用しますか? 'NestedClass'はパッケージプライベートなので、' SOExample.NestedClass'を介して 'NestedClass'にアクセスすることはできません。 – Pshemo

+0

'NestedClass'は実際に興味のあるメソッドを含むいくつかのパブリックインターフェイスを実際に実装することは可能でしょうか?その場合、 'Map 'または 'Map 'を継承します。 – Pshemo

+0

@Pshemo myMapには、収束までに1日かかる非常に遅い離散イベントシミュレーションによって作成される約500kの値があります。 myMapをシリアライズし、すぐにデシリアライズできるようにそのデータを手元に置いておきたいと思います。 – andrew

答えて

1

ネストされたクラスにアクセスできないため、コンパイル時エラーが発生します。あなたが行うことができます

唯一のことは、このクラスの参照を使用しないようにすることです:

Field f = example.getClass().getDeclaredField("myMap"); 
f.setAccessible(true); 
Map map = (Map) f.get(example); 
Object obj = map.get("1"); 

あなたがフィールドにアクセスし、反射してobjインスタンスでメソッドを呼び出すことができます。

0

@AdamSkywalkerが正しいアプローチを提供しました。私は完成のためだけに最終的な作業例を掲示しています。

public class SOExampleMyPackage { 
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 
     SOExample example = new SOExample(); 
     example.populateMyMap(); 

     // Make the example.myMap field accessible 
     Field f = example.getClass().getDeclaredField("myMap"); 
     f.setAccessible(true); 

     ///// 
     //SOLUTION start 
     ///// 
     Map<String, Object> myMapHere = (Map<String, Object>) f.get(example); 

     // Loop through entries and reflect out the values 
     Map<String, Integer> finalMap = new HashMap<String, Integer>(); 
     for (String k: myMapHere.keySet()){ 
      Field f2 = myMapHere.get(k).getClass().getDeclaredField("data"); 
      f2.setAccessible(true); 
      finalMap.put(k, (Integer) f2.get(myMapHere.get(k))); 
     } 
     ///// 
     //SOLUTION end 
     ///// 

     // Test it all 
     for (String k: finalMap.keySet()){ 
      System.out.println("Key: " + k + " Value: " + finalMap.get(k)); 
     } 
    } 
} 
関連する問題