代码之家  ›  专栏  ›  技术社区  ›  Alexius DIAKOGIANNIS

获取类的所有字段,包括其他类的字段

  •  -1
  • Alexius DIAKOGIANNIS  · 技术社区  · 7 年前

    基于这个问题 Get all Fields of class hierarchy

    package com.foo.bar
    
    public class Employee{ 
    
        private String firstName; 
    
        private String id; 
    
        private Address address; 
    
    // Getters and Setters follow
    
    }
    

    班级地址是

    package com.foo.bar
    
    public class Address{ 
    
        private String street; 
    
        private String streetNum; 
    
    // Getters and Setters follow
    
    }
    

    我想用来自表单中Employee的所有类的所有字段填充一个列表

    • 员工名
    • 员工id
    • Employee.Address.streetNum公司

    我感兴趣的所有类要么和Employee类ex在同一个包中 com.foo.bar 或者在我已经知道的特定包中。

    谢谢

    另外,我正在使用jdk7

    2 回复  |  直到 7 年前
        1
  •  2
  •   ernest_k Petronella    7 年前

    下面是检查类声明字段的简单方法:

    static Set<Field> getFields(Class<?> cls) {
        Set<Field> set = new HashSet<>();
    
        for (Field f : cls.getDeclaredFields()) {
            set.add(f);
    
            //a filter to avoid standard classes. Update accordingly
            if (f.getType().getName().startsWith("com.foo.bar")) {
                set.addAll(getFields(f.getType()));
            }
        }
    
        return set;
    }
    

    一个简单的电话:

    public static void main(String[] args) {
        Set<Field> all = getFields(Employee.class);
        for (Field f : all) {
            System.out.println(String.format("%s.%s", 
                 f.getDeclaringClass().getSimpleName(), f.getName()));
        }
    }
    

    在示例类中,上面打印了:

    Employee.firstName
    Employee.address
    Address.street
    Address.streetNum
    Employee.id
    

    下面是一个等价的Java8+版本(只检查树的两个级别):

    Stream.of(Employee.class.getDeclaredFields())
            .flatMap(f -> Stream.concat(Stream.of(f), 
                    Stream.of(f.getType().getDeclaredFields())))
            .filter(f -> f.getDeclaringClass()
                          .getPackage()
                          .getName()
                          .startsWith("com.foo.bar"))
            .map(f -> String.format("%s.%s", 
                        f.getDeclaringClass().getSimpleName(), f.getName()))
            .forEach(System.out::println);
    

    这个 filter 以上用于将检查的类限制为当前包中的类(相应地更改)。没有它,一个人就得 String 的字段等。

    distinct() 如果出现重复项,则删除重复项。

        2
  •  1
  •   Alexius DIAKOGIANNIS    7 年前

    谢谢大家,我创建了一个递归函数。功能如下

    private void getClassFields(final Class c,final List<String> fields) throws ClassNotFoundException {
        for(Field f : c.getDeclaredFields()){
            if(f.getType().getName().contains("foo.bar")){
                getClassFields(Class.forName(f.getType().getName()),fields);
            }else {
                fields.add(f.getName());
            }
        }
    }