任务: 您需要获取指定类的所有字段,包括来自所有超类的私有和包含字段。 Usuall方法是重新获得字段:
private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) {
fields.addAll(Arrays.asList(type.getDeclaredFields()));
if (type.getSuperclass() != null) {
getAllFieldsRecursive(fields, type.getSuperclass());
}
}
然而,案例并未涵盖被覆盖的字段。 运行代码:
class A {String myfield; String otherAField}
class B extends class A {String myField; String otherBField}
会给出结果: String B.myfield; String B.otherBField; String A.myfield,String A.otherField
使用Set无济于事,因为String A.myfield不等于B.myfield
下面的解决方案
答案 0 :(得分:0)
/**
* Collect all fields declared, including superclasses.
* @param type class
* @return
*/
public static List<Field> getAllFields(Class<?> type) {
List<Field> fields = new ArrayList<>();
getAllFieldsRecursive(fields, type);
return fields;
}
/**
* Get fields recursively, starting from child.
* Starting from child is important to support fields overriding.
* @param fields all fields collected
* @param type currently scanned class
* Example:
* class A {String myfield; String otherField}
* class B extends class A {String myField; String bField}
* Result: String B.myfield; String B.bField; String A.otherField
*/
private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) {
List<Field> declaredFields = Arrays.asList(type.getDeclaredFields()); //Start from child
for (Field declaredField : declaredFields){
if (!genericContainsField(declaredField, fields))
fields.add(declaredField); //if field is not overridden in child, add it
}
if (type.getSuperclass() != null) {
getAllFieldsRecursive(fields, type.getSuperclass());
}
}
/**
*
* @param declaredField field we are comparing
* @param fields current fields list
* @return
*/
private static boolean genericContainsField(Field declaredField, List<Field> fields){
for (Field field:fields){
if (genericEqualsFields(field, declaredField))
return true;
}
return false;
}
/**
* Compares this {@code Field} against the specified object. Returns
* true if the objects are the same. Two {@code Field} objects are the same if
* they were have the same name and type.
* Declared by the same class is NOT needed
* Hack for Generic lookup, based on Field.equals()
*/
private static boolean genericEqualsFields(Field obj, Field other) {
return (obj.getName() == other.getName())
&& (obj.getType() == other.getType());
}