Java 리플렉션을 사용할 때 getFields
메소드와 메소드 의 차이점에 대해 약간 혼란 스럽습니다 getDeclaredFields
.
나는 getDeclaredFields
클래스의 모든 필드에 액세스 할 수 있고 getFields
공개 필드 만 반환 한다는 것을 읽었습니다 . 이 경우 항상 왜 항상 사용하지 getDeclaredFields
않습니까?
누군가 이것에 대해 자세히 설명하고 두 방법의 차이점과 언제 어떻게 다른 것을 사용하고 싶습니까?
답변
모든 public
필드는 전체 클래스 계층 구조입니다.
현재 클래스가 상속 할 수있는 기본 클래스가 아닌 액세스 가능성에 관계없이 현재 클래스에 대해서만 모든 필드.
모든 필드를 계층 구조로 가져 오기 위해 다음 함수를 작성했습니다.
public static Iterable<Field> getFieldsUpTo(@Nonnull Class<?> startClass,
@Nullable Class<?> exclusiveParent) {
List<Field> currentClassFields = Lists.newArrayList(startClass.getDeclaredFields());
Class<?> parentClass = startClass.getSuperclass();
if (parentClass != null &&
(exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) {
List<Field> parentClassFields =
(List<Field>) getFieldsUpTo(parentClass, exclusiveParent);
currentClassFields.addAll(parentClassFields);
}
return currentClassFields;
}
이 exclusiveParent
필드는 필드 검색을 방지하기 위해 제공됩니다 Object
. 그것은있을 수 있습니다 null
당신이 원하는 경우 Object
필드를.
명확히하기 위해 Lists.newArrayList
구아바 에서 온다.
최신 정보
참고로, 위 코드는 ReflectionUtils의 LibEx 프로젝트에서 GitHub에 게시되었습니다 .
답변
이미 언급했듯이, Class.getDeclaredField(String)
필드 Class
를 호출 한 필드 만 봅니다 .
계층 구조 Field
에서 a를 검색 Class
하려면 다음과 같은 간단한 기능을 사용할 수 있습니다.
/**
* Returns the first {@link Field} in the hierarchy for the specified name
*/
public static Field getField(Class<?> clazz, String name) {
Field field = null;
while (clazz != null && field == null) {
try {
field = clazz.getDeclaredField(name);
} catch (Exception e) {
}
clazz = clazz.getSuperclass();
}
return field;
}
private
예를 들어 수퍼 클래스에서 필드 를 찾는 데 유용합니다 . 또한 값을 수정하려면 다음과 같이 사용할 수 있습니다.
/**
* Sets {@code value} to the first {@link Field} in the {@code object} hierarchy, for the specified name
*/
public static void setField(Object object, String fieldName, Object value) throws Exception {
Field field = getField(object.getClass(), fieldName);
field.setAccessible(true);
field.set(object, value);
}
답변
public Field[] getFields() throws SecurityException
이 Class 객체가 나타내는 클래스 또는 인터페이스 의 액세스 가능한 모든 공개 필드 를 반영하는 Field 객체를 포함하는 배열을 리턴 합니다. 반환 된 배열의 요소는 정렬되지 않으며 특정 순서가 아닙니다. 이 메소드는 클래스 또는 인터페이스에 액세스 가능한 공용 필드가 없거나 배열 클래스, 기본 유형 또는 void를 나타내는 경우 길이가 0 인 배열을 리턴합니다.
특히,이 Class 객체가 클래스를 나타내는 경우,이 메소드는 이 클래스와 모든 슈퍼 클래스의 공개 필드를 돌려줍니다 . 이 Class 객체가 인터페이스를 나타내는 경우,이 메소드는이 인터페이스와 모든 슈퍼 인터페이스의 필드를 돌려줍니다.
이 클래스는 배열 클래스의 암시 적 길이 필드를 반영하지 않습니다. 사용자 코드는 Array 클래스의 메소드를 사용하여 배열을 조작해야합니다.
public Field[] getDeclaredFields() throws SecurityException
이 Class 객체가 나타내는 클래스 또는 인터페이스가 선언 한 모든 필드를 반영하는 Field 객체의 배열을 리턴 합니다. 여기 에는 공개, 보호, 기본 (패키지) 액세스 및 개인 필드가 포함되지만 상속 된 필드는 제외 됩니다. 반환 된 배열의 요소는 정렬되지 않으며 특정 순서가 아닙니다. 이 메소드는 클래스 또는 인터페이스가 필드를 선언하지 않거나이 Class 객체가 기본 유형, 배열 클래스 또는 void를 나타내는 경우 길이가 0 인 배열을 리턴합니다.
모든 부모 클래스의 모든 필드가 필요한 경우 어떻게해야합니까? 일부 코드가 필요합니다 (예 : https://stackoverflow.com/a/35103361/755804) .
public static List<Field> getAllModelFields(Class aClass) {
List<Field> fields = new ArrayList<>();
do {
Collections.addAll(fields, aClass.getDeclaredFields());
aClass = aClass.getSuperclass();
} while (aClass != null);
return fields;
}