2016-07-05 3 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'가 패키지 private이기 때문에'SOExample.NestedClass'를 통해'NestedClass'에 접근 할 수 없다고 말하면 옳습니다. – Pshemo

+0

'NestedClass'는 실제로 당신이 관심있는 메소드를 포함하고있는 공용 인터페이스를 구현할 수 있습니까? 이 경우'Map '또는'Map '를 확장합니다. – Pshemo

+0

@Pshemo myMap에는 매우 느린 이산 이벤트 시뮬레이션을 통해 생성되는 약 500k 값이 있습니다.이 시뮬레이션은 수렴하는 데 하루가 걸릴 수 있습니다. 우리는 myMap을 직렬화하고 그 데이터를 손쉽게 가지고있어서 우리가 그것을 deserialize 할 수 있기를 원합니다. – 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)); 
     } 
    } 
}