我发现可以通过 class.getDeclaredFields();
获取继承的成员变量,
并使用 class.getFields()
访问私有成员变量,
但我正在寻找私有继承字段。
我如何实现这个?
我发现可以通过 class.getDeclaredFields();
获取继承的成员变量,
并使用 class.getFields()
访问私有成员变量,
但我正在寻找私有继承字段。
我如何实现这个?
这个示例演示了如何解决这个问题:
import java.lang.reflect.Field;
class Super {
private int i = 5;
}
public class B extends Super {
public static void main(String[] args) throws Exception {
B b = new B();
Field f = b.getClass().getSuperclass().getDeclaredField("i");
f.setAccessible(true);
System.out.println(f.get(b));
}
}
(或使用Class.getDeclaredFields
获取所有字段的数组。)
输出:
5
getSuperclass()
进行递归,直到达到 null
。 - aioobegetDeclaredFields()[0]
或getDeclaredField("i")
,而是在接下来的两个语句中重复[0]
数组访问? - HolgergetDeclaredFields
的演示。答案已经更新。 - aioobe在这里最好的方法是使用访问者模式,查找类中的所有字段和超类,并对它们执行回调操作。
Spring框架有一个很好用的Utility类ReflectionUtils
,它定义了一个方法可以遍历所有超类的字段并进行回调:ReflectionUtils.doWithFields()
在目标类中调用给定回调函数以处理所有字段,一直到类层次结构的顶部获取所有声明的字段。
参数:
- clazz - 目标类
- fc - 对每个字段调用的回调函数
- ff - 确定应该将回调函数应用于哪些字段的过滤器
ReflectionUtils.doWithFields(RoleUnresolvedList.class,
new FieldCallback(){
@Override
public void doWith(final Field field) throws IllegalArgumentException,
IllegalAccessException{
System.out.println("Found field " + field + " in type "
+ field.getDeclaringClass());
}
},
new FieldFilter(){
@Override
public boolean matches(final Field field){
final int modifiers = field.getModifiers();
// no static fields please
return !Modifier.isStatic(modifiers);
}
});
在javax.management.relation.RoleUnresolvedList类中找到一个名为private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe的字段
在javax.management.relation.RoleUnresolvedList类中找到一个名为private transient boolean javax.management.relation.RoleUnresolvedList.tainted的字段
在java.util.ArrayList类中找到一个名为private transient java.lang.Object[] java.util.ArrayList.elementData的字段
在java.util.ArrayList类中找到一个名为private int java.util.ArrayList.size的字段
在java.util.AbstractList类中找到一个名为protected transient int java.util.AbstractList.modCount的字段
private List<Field> getInheritedPrivateFields(Class<?> type) {
List<Field> result = new ArrayList<Field>();
Class<?> i = type;
while (i != null && i != Object.class) {
Collections.addAll(result, i.getDeclaredFields());
i = i.getSuperclass();
}
return result;
}
private List<Field> getInheritedPrivateFields(Class<?> type) {
List<Field> result = new ArrayList<Field>();
Class<?> i = type;
while (i != null && i != Object.class) {
for (Field field : i.getDeclaredFields()) {
if (!field.isSynthetic()) {
result.add(field);
}
}
i = i.getSuperclass();
}
return result;
}
public static Field getField(Class<?> clazz, String fieldName) {
Class<?> tmpClass = clazz;
do {
try {
Field f = tmpClass.getDeclaredField(fieldName);
return f;
} catch (NoSuchFieldException e) {
tmpClass = tmpClass.getSuperclass();
}
} while (tmpClass != null);
throw new RuntimeException("Field '" + fieldName
+ "' not found on class " + clazz);
}
(根据这个答案)事实上,我使用了一个复杂的类型层次结构,因此你的解决方案并不完整。 我需要进行递归调用以获取所有私有继承字段。 以下是我的解决方案
/**
* Return the set of fields declared at all level of class hierachy
*/
public static List<Field> getAllFields(Class<?> clazz) {
return getAllFieldsRec(clazz, new ArrayList<>());
}
private static List<Field> getAllFieldsRec(Class<?> clazz, List<Field> list) {
Class<?> superClazz = clazz.getSuperclass();
if (superClazz != null) {
getAllFieldsRec(superClazz, list);
}
list.addAll(Arrays.asList(clazz.getDeclaredFields()));
return list;
}
private static Field getField(Class<?> clazz, String fieldName) {
Class<?> tmpClass = clazz;
do {
for ( Field field : tmpClass.getDeclaredFields() ) {
String candidateName = field.getName();
if ( ! candidateName.equals(fieldName) ) {
continue;
}
field.setAccessible(true);
return field;
}
tmpClass = tmpClass.getSuperclass();
} while ( clazz != null );
throw new RuntimeException("Field '" + fieldName +
"' not found on class " + clazz);
}
在 Model Citizen 中,我需要为蓝图添加继承字段的支持。我提出了这种方法,它更为简洁,可以检索类的字段和继承字段。
private List<Field> getAllFields(Class clazz) {
List<Field> fields = new ArrayList<Field>();
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
Class superClazz = clazz.getSuperclass();
if(superClazz != null){
fields.addAll(getAllFields(superClazz));
}
return fields;
}