如何授予对通过反射检索的所有私有字段值的访问权限?

时间:2017-05-31 09:57:18

标签: java reflection

是否可以在不使用field.setAccessible(true);的情况下获取字段值?

 Field field = object.getClass().getDeclaredField(fieldName);    
 field.setAccessible(true);
 Object value = field.get(object);

我的意思是,我可以简单地授予对特定类的所有私有字段的访问权限,而不必在每次读取时调用setter吗?

2 个答案:

答案 0 :(得分:4)

您不必为每个字段访问重复该操作。每个类/字段只需执行一次,但有一种有效的方法:

static final class Accessor extends ClassValue<Map<String,Field>> {
    @Override protected Map<String, Field> computeValue(Class<?> type) {
        Field[] fields=type.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);
        Map<String,Field> map=new HashMap<>(fields.length);
        for(Field f: fields) map.put(f.getName(), f);
        return map;
    }
}
static final Accessor FIELD_ACCESSOR = new Accessor();

使您的访问变得像

一样简单
Object value = FIELD_ACCESSOR.get(o.getClass()).get(fieldName).get(o);

请注意,ClassValue负责每个类只执行一次操作,而缓存的值不会阻止类垃圾收集,AccessibleObject.setAccessible(…)将一次应用于所有声明的字段。

但请记住,这些只是实际类的声明字段,您必须手动迭代超类层次结构以搜索其字段。字段名称不必在类层次结构中是唯一的。

答案 1 :(得分:1)

不,你不能。什么是为了什么?您可以准备一次Field对象,对其进行缓存并将其用于多次读取。

 // do it once
 Field field = object.getClass().getDeclaredField(fieldName);    
 field.setAccessible(true);

 // use many times:
 for(million times)
     Object value = field.get(object);