상속 된 구성원을 통해 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
답변
여기에서 가장 좋은 방법은 방문자 패턴을 사용하여 클래스의 모든 필드와 모든 수퍼 클래스를 찾아 콜백 작업을 실행하는 것입니다.
이행
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);
}
});
산출:
발견 된 필드 private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe in type 클래스 javax.management.relation.RoleUnresolvedList
Found field private transient boolean javax.management.relation.RoleUnresolvedList.tainted in type class javax.management.relation.RoleUnresolvedList
Found field private transient java.lang.Object [] 클래스 java.util.ArrayList 유형의 java.util.ArrayList.elementData
발견 된 필드 private int 클래스 java.util.ArrayList 유형의 java.util.ArrayList.size
발견 된 필드 보호 된 transient int java. 클래스 java.util.AbstractList 유형의 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;
}
EclEmma 와 같은 코드 커버리지 도구를 사용하는 경우주의해야합니다 . 각 클래스에 숨겨진 필드를 추가합니다. 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;
}
답변
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 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;
}
답변
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;
}
답변
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);
}