Java 使用泛型获取所有字段

Java 使用泛型获取所有字段,java,generics,Java,Generics,任务: 您需要从所有超类获取指定类的所有字段,包括private和inluding字段。 通常的方法是循环获取字段: private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) { fields.addAll(Arrays.asList(type.getDeclaredFields())); if (type.getSuperclass() != null)

任务: 您需要从所有超类获取指定类的所有字段,包括private和inluding字段。 通常的方法是循环获取字段:

private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) {
    fields.addAll(Arrays.asList(type.getDeclaredFields()));   
    if (type.getSuperclass() != null) {
        getAllFieldsRecursive(fields, type.getSuperclass());
    }
}
将给出以下结果: 字符串B.myfield;字符串B.otherBField;字符串A.myfield,字符串A.otherField

使用Set不会有帮助,因为字符串A.myfield不等于B.myfield

下面的解决方案

/**
/**
 * 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());
}
*收集所有声明的字段,包括超类。 *@param类型类 *@返回 */ 公共静态列表getAllFields(类类型){ 列表字段=新的ArrayList(); getAllFieldsRecursive(字段,类型); 返回字段; } /** *从子级开始递归获取字段。 *从子级开始对于支持字段重写很重要。 *@param fields收集的所有字段 *@param-type当前扫描的类 *例如: *类{String myfield;String otherField} *类B扩展类A{String myField;String bField} *结果:字符串B.myfield;字符串B.B字段;字符串A.otherField */ 私有静态void getAllFieldsRecursive(列表字段,类类型){ List declaredFields=Arrays.asList(type.getDeclaredFields());//从子级开始 for(字段declaredField:declaredFields){ 如果(!genericContainsField(declaredField,fields)) fields.add(declaredField);//如果字段在子级中未被重写,则添加它 } if(type.getSuperclass()!=null){ getAllFieldsRecursive(字段,类型.getSuperclass()); } } /** * *@param declaredField我们正在比较 *@param字段当前字段列表 *@返回 */ 私有静态布尔genericContainsField(字段declaredField,列表字段){ 用于(字段:字段){ if(一般质量字段(字段、申报字段)) 返回true; } 返回false; } /** *将此{@code Field}与指定的对象进行比较。退换商品 *如果对象相同,则为true。两个{@code Field}对象是相同的,如果 *它们的名称和类型相同。 *不需要由同一类声明 *基于Field.equals()的通用查找的Hack */ 私有静态布尔genericEqualsFields(字段obj、字段other){ 返回值(obj.getName()==other.getName()) &&(obj.getType()==其他.getType()); }
“但是,本案例不包括覆盖字段。”没有覆盖字段。在那里显示四个字段是完全正确的。
B
的实例有四个独立的字段。还不清楚这与泛型有什么关系…@Jon Skeet,不,显示所有4个字段并不总是正确的。例如,在某些情况下,您只需要知道字段的最新版本及其支持的注释。是的,字段是隐藏的,而不是被覆盖的。没有“最后版本”这样的东西。您的问题是:“您需要获取指定类的所有字段,包括来自所有超类的private和inluding字段。”在您给出的示例中,有四个这样的字段。如果你确实有不同的任务,你应该在问题中陈述。在描述的任务中显示所有4个字段总是正确的。
/**
 * 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());
}