在Java中通过反射访问私有继承字段
我找到了一种通过在Java中通过反射访问私有继承字段,java,reflection,inheritance,private-members,Java,Reflection,Inheritance,Private Members,我找到了一种通过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) thro
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));
}
}
(或用于所有字段的数组。)
输出:
5
事实上,我使用了一个复杂的类型层次结构,所以您的解决方案是不完整的。
我需要进行递归调用以获取所有私有继承字段。
这是我的解决办法
/**
* Return the set of fields declared at all level of class hierachy
*/
public Vector<Field> getAllFields(Class clazz) {
return getAllFieldsRec(clazz, new Vector<Field>());
}
private Vector<Field> getAllFieldsRec(Class clazz, Vector<Field> vector) {
Class superClazz = clazz.getSuperclass();
if(superClazz != null){
getAllFieldsRec(superClazz, vector);
}
vector.addAll(toVector(clazz.getDeclaredFields()));
return vector;
}
/**
*返回在类层次结构的所有级别声明的字段集
*/
公共向量getAllFields(clazz类){
返回getAllFieldsRec(clazz,new Vector());
}
私有向量getAllFieldsRec(类clazz,向量向量){
类superClazz=clazz.getSuperclass();
if(超级杯!=null){
getAllFieldsRec(超级Lazz,矢量);
}
addAll(toVector(clazz.getDeclaredFields());
返回向量;
}
这样就可以了:
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;
}
私有列表getInheritedPrivateFields(类类型){
列表结果=新建ArrayList();
i类=类型;
而(i!=null&&i!=Object.class){
Collections.addAll(result,i.getDeclaredFields());
i=i.getSuperclass();
}
返回结果;
}
如果您使用这样的代码覆盖工具,您必须小心:它们会为您的每个类添加一个隐藏字段。在EclEmma的情况下,这些字段被标记为合成字段,您可以按如下方式过滤它们:
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;
}
私有列表getInheritedPrivateFields(类类型){
列表结果=新建ArrayList();
i类=类型;
而(i!=null&&i!=Object.class){
for(字段:i.getDeclaredFields()){
如果(!field.isSynthetic()){
结果。添加(字段);
}
}
i=i.getSuperclass();
}
返回结果;
}
这里最好的方法是使用do查找类和所有超类中的所有字段,并对它们执行回调操作
实施
Spring有一个很好的实用程序类,它就是这样做的:它定义了一个方法,通过回调循环所有超类的所有字段:
文档:
对目标类中的所有字段调用给定回调,
向上移动类层次结构以获取所有声明的字段
参数:
-clazz-要分析的目标类
-fc-为每个字段调用的回调
-ff-确定要应用回调的字段的筛选器
示例代码:
输出:
在类型类javax.management.relation.RoleUnresolvedList中找到字段private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe
在类型类javax.management.relation.RoleUnresolvedList中找到了受污染的字段私有临时布尔javax.management.relation.RoleUnresolvedList
在类型类java.util.ArrayList中找到字段private transient java.lang.Object[]java.util.ArrayList.elementData
在类型类java.util.ArrayList中找到字段private int java.util.ArrayList.size
在类型类java.util.AbstractList中找到受字段保护的瞬态int java.util.AbstractList.modCount
私有静态字段getField(类clazz,字符串fieldName){
类别tmpClass=clazz;
做{
for(字段:tmpClass.getDeclaredFields()){
字符串candidateName=field.getName();
如果(!candidateName.equals(fieldName)){
继续;
}
字段。setAccessible(true);
返回字段;
}
tmpClass=tmpClass.getSuperclass();
}while(clazz!=null);
抛出新的RuntimeException(“字段“”+fieldName+
“‘未在类上找到’+clazz);
}
公共静态字段getField(类clazz,字符串fieldName){
类别tmpClass=clazz;
做{
试一试{
字段f=tmpClass.getDeclaredField(字段名);
返回f;
}捕获(无此字段例外){
tmpClass=tmpClass.getSuperclass();
}
}while(tmpClass!=null);
抛出新的RuntimeException(“字段“”+fieldName
+“‘未在类上找到’+clazz);
}
(基于答案)我需要在中添加对蓝图继承字段的支持。我派生了这个方法,它在检索类的字段+继承字段时更加简洁
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;
}
私有列表getAllFields(类clazz){
列表字段=新的ArrayList();
addAll(Arrays.asList(clazz.getDeclaredFields());
类superClazz=clazz.getSuperclass();
if(超级杯!=null){
addAll(getAllFields(superClazz));
}
返回字段;
}
“私有继承字段”不存在。如果一个字段是私有的,它不会被继承,并且只保留在父类的范围内。要访问父私有字段,您必须首先访问父类(参见aioobe的回答),也就是说,受保护的字段是继承的,但您也必须这样做才能通过反射获得它们。然而,他的解决方案可能会重复,不是吗?Vector是糟糕的旧代码。请使用集合框架中的当前数据结构(ArrayList在大多数情况下是足够的)@aperkins aioobe的答案看起来像我的,但我找到了,然后我看到了答案@seanizer Vector并没有那么古老,它是集合API的一个成员“从Java2平台v1.2开始,这个类已经被改造为实现List,所以它成为Java集合框架的一部分。”在1.2中被改造?如果那不是旧的,那是什么?资料来源:Vector的开销很大,因为所有内容都是同步的。在需要同步的地方,java.util.concurrent中有更好的类。Vector、Hashtable和StringBuffer在大多数情况下都应该被ArrayList、HashMap和StringBuilder替换感谢您对合成字段的评论,EMMA也这么做
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);
}
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);
}
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;
}