反射访问嵌套类的值

时间:2016-07-05 20:51:55

标签: java reflection

我知道这是一个糟糕的代码设计,但作为一个临时的黑客......

我需要访问私有映射,其中值是静态嵌套类的初始化。在下面的示例中,我想从不同的包中访问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);
    }
}

我很感激有关如何解决这个问题的任何想法。

2 个答案:

答案 0 :(得分:1)

您收到编译时错误,因为无法访问嵌套类。

你唯一能做的就是避免使用这个类的引用:

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

您可以使用反射访问obj实例上的字段并调用方法。

答案 1 :(得分: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));
        }
    }
}