2009-06-25 5 views
91

'ParentObj'에서 확장 한 Java 객체 'ChildObj'가 있습니다. 이제, Java reflection 메커니즘을 사용하여 상속 된 속성을 포함하여 ChildObj의 모든 속성 이름과 값을 검색 할 수 있다면?Java Reflection을 사용하여 상속 된 속성 이름/값 검색

Class.getFields은 나에게 공용 속성 배열을 제공하고 Class.getDeclaredFields은 나에게 모든 필드의 배열을 제공하지만 상속 된 필드 목록을 포함하지는 않습니다.

상속 된 속성을 검색 할 수있는 방법이 있습니까?

답변

132

아니요, 직접 작성해야합니다.

public static List<Field> getAllFields(List<Field> fields, Class<?> type) { 
    fields.addAll(Arrays.asList(type.getDeclaredFields())); 

    if (type.getSuperclass() != null) { 
     getAllFields(fields, type.getSuperclass()); 
    } 

    return fields; 
} 

@Test 
public void getLinkedListFields() { 
    System.out.println(getAllFields(new LinkedList<Field>(), LinkedList.class)); 
} 
+1

예. 그 생각. 다른 방법이 있는지 확인하고 싶었습니다. 감사. :) – Veera

+0

그것이 효과가있다. 감사. – Veera

+6

변경 가능한 인수를 전달한 후 반환하는 것은 좋지 않습니다. fields.addAll (type.getDeclaredFields()); add를 사용하여 for 루프를 개선하는 것보다 더 일반적입니다. –

5

당신은 전화를해야합니다 :

Class.getSuperclass().getDeclaredFields() 

필요에 따라 상속 계층 구조를 재귀는 Class.getSuperClass()에라는 간단한 재귀 방법이다.

1

당신은 시도 할 수 있습니다 : "DidYouMeanThatTomHa ..."재귀 솔루션은 OK입니다

0
private static void addDeclaredAndInheritedFields(Class c, Collection<Field> fields) { 
    fields.addAll(Arrays.asList(c.getDeclaredFields())); 
    Class superClass = c.getSuperclass(); 
    if (superClass != null) { 
     addDeclaredAndInheritedFields(superClass, fields); 
    } 
} 
71
public static List<Field> getAllFields(Class<?> type) { 
     List<Field> fields = new ArrayList<Field>(); 
     for (Class<?> c = type; c != null; c = c.getSuperclass()) { 
      fields.addAll(Arrays.asList(c.getDeclaredFields())); 
     } 
     return fields; 
    } 
+9

이것은 내가 선호하는 솔루션이지만 주어진 클래스의 필드도 반환하기 때문에 "getAllFields"라고합니다. – Pino

+0

나는 Pino – Marquez

+3

에 동의한다. 그러나 나는 매우 재귀를 좋아하지만 (재미있다!), 나는이 방법의 가독성과보다 직관적 인 매개 변수 (새로운 컬렉션이 통과하지 않아도 됨), 더 이상 if (for 절에 암시 적) 및 필드 자체에 대한 반복 없음을 선호합니다. –

2
private static void addDeclaredAndInheritedFields(Class<?> c, Collection<Field> fields) { 
    fields.addAll(Arrays.asList(c.getDeclaredFields())); 
    Class<?> superClass = c.getSuperclass(); 
    if (superClass != null) { 
     addDeclaredAndInheritedFields(superClass, fields); 
    }  
} 

이 유일한 작은 문제가있다 그들은 선언되고 상속 된 멤버들의 수퍼 셋을 반환한다. getDeclaredFields() 메서드는 private 메서드도 반환합니다. 따라서 전체 수퍼 클래스 계층 구조를 탐색하면 수퍼 클래스에 선언 된 모든 개인 필드가 포함되며 상속받지 않습니다.

Modifier.isPublic을 사용하는 간단한 필터 || Modifier.isProtected 술어는 할 것 :

import static java.lang.reflect.Modifier.isPublic; 
import static java.lang.reflect.Modifier.isProtected; 

(...) 

List<Field> inheritableFields = new ArrayList<Field>(); 
for (Field field : type.getDeclaredFields()) { 
    if (isProtected(field.getModifiers()) || isPublic(field.getModifiers())) { 
     inheritableFields.add(field); 
    } 
} 
3

위의 솔루션의 버전 작업

Class parentClass = getClass().getSuperclass(); 
    if (parentClass != null) { 
     parentClass.getDeclaredFields(); 
    } 
25

을 당신이, Apache Commons Lang 버전 3.2 이상이 FieldUtils.getAllFieldsList를 제공 달성하기 위해 라이브러리에 의존하고 싶었 대신하는 경우 :

import java.lang.reflect.Field; 
import java.util.AbstractCollection; 
import java.util.AbstractList; 
import java.util.AbstractSequentialList; 
import java.util.Arrays; 
import java.util.LinkedList; 
import java.util.List; 

import org.apache.commons.lang3.reflect.FieldUtils; 
import org.junit.Assert; 
import org.junit.Test; 

public class FieldUtilsTest { 

    @Test 
    public void testGetAllFieldsList() { 

     // Get all fields in this class and all of its parents 
     final List<Field> allFields = FieldUtils.getAllFieldsList(LinkedList.class); 

     // Get the fields form each individual class in the type's hierarchy 
     final List<Field> allFieldsClass = Arrays.asList(LinkedList.class.getFields()); 
     final List<Field> allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields()); 
     final List<Field> allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields()); 
     final List<Field> allFieldsParentsParentsParent = Arrays.asList(AbstractCollection.class.getFields()); 

     // Test that `getAllFieldsList` did truly get all of the fields of the the class and all its parents 
     Assert.assertTrue(allFields.containsAll(allFieldsClass)); 
     Assert.assertTrue(allFields.containsAll(allFieldsParent)); 
     Assert.assertTrue(allFields.containsAll(allFieldsParentsParent)); 
     Assert.assertTrue(allFields.containsAll(allFieldsParentsParentsParent)); 
    } 
} 
+3

붐! 나는 바퀴를 다시 발명하지 않는 것을 좋아합니다. 건배. –

0

짧은 적은 객체를 인스턴스화? ^^

private static Field[] getAllFields(Class<?> type) { 
    if (type.getSuperclass() != null) { 
     return (Field[]) ArrayUtils.addAll(getAllFields(type.getSuperclass()), type.getDeclaredFields()); 
    } 
    return type.getDeclaredFields(); 
} 
+0

HI @Alexis LEGROS : ArrayUtils에서 기호를 찾을 수 없습니다. –

+1

이 클래스는 Apache Commons Lang의 클래스입니다. –

+0

아파치는 이미이 질문을 처리 할 수있는 FieldUtils.getAllFields 함수를 가지고 있습니다. –

4

사용 반사 라이브러리 :

public Set<Field> getAllFields(Class<?> aClass) { 
    return org.reflections.ReflectionUtils.getAllFields(aClass); 
} 
관련 문제