繁体   English   中英

如何使用 java 反射迭代列表类型的字段

[英]How to iterate Field of type List using java reflection

我有一个名为 class 的用户,它有这样的帐户列表 class 对象

 public class User{
   private List<Account> accounts = new ArrayList<Account>();
 }

帐户 object 有一个瞬态字段,我想找到它并用它做一些事情

public class Account{
  private transient openDateInOrgDateFormat;
}

我想使用反射找到这个字段,然后检查它是否瞬态然后做一些事情。 通过反射如何找到类型集合的字段然后迭代它并找到列表中的 object 中的字段是否是瞬态的。

由于我不知道究竟是什么阻止了您编写代码,因此这里有一些工具应该会有所帮助:

  • 获取在类使用中声明的字段数组

    Field[] fields = User.class.getDeclaredFields()
  • 检查分配给字段的类型是什么,请使用field.getType()

  • 检查类型是否与 List 等其他类型相同,只需使用

    type.equals(List.class);
  • 检查一种类型是否属于某个祖先的家族(比如 List 是 Collection 的子类型)使用isAssignableFrom类的

    Collection.class.isAssignableFrom(List.class)
  • 检查字段的修饰符,如transient使用

    Modifier.isTransient(field.getModifiers())
  • 要访问特定实例中字段持有的,请使用

    Object value = field.get(instanceWithThatField)

    但在private字段的情况下,您需要首先通过field.setAccessible(true)使其可访问。 然后,如果您确定对象value类型是什么,则可以将其强制转换为该类型,例如

    List<Account> list = (List<Account>) value;

    或者在一行中执行两个操作,就像你的情况一样

    List<Account> list = (List<Account>) field.get(userObject);

    您可以稍后以您想要的方式迭代
    for(Account acc : list){ /*handle each acc*/ }

您可以使用数组流来做到这一点:

Object obj;
Field[] fields = obj.getClass().getDeclaredFields();
List<Field> fieldOfTypeList =  Arrays.stream(fields).distinct().filter(field -> field.getType().equals(List.class)).collect(Collectors.toList());

详细说明@Pshemo 的回答,步骤如下:(请注意,由于类型擦除,从 Class 获取特定类型参数比从 Object 更容易。)

  1. 循环遍历 User 中的字段。
  2. 对于具有预定义类型的字段,检查 transcience。
  3. 对于 Collections,获取其参数的类型,如果它是自定义类型,则对该 class 运行递归。

例如

    private static void checkTranscience(Class<?> clazz) {
    for (Field field : clazz.getDeclaredFields()) {
        field.setAccessible(true);
        System.out.println("Transience " + Modifier.isTransient(field.getModifiers()) + " for " + field.getName());
        Class<?> fieldClass;
        if (Collection.class.isAssignableFrom(field.getType())) {
            //In case of Parameterized List or Set Field, extract genericClassType
            fieldClass = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
        } else {
            fieldClass = field.getType();
        }
        //Assuming Account belongs to "com.examplepackage.accountpackage" package to narrow down recursives to custom Types only
        if (fieldClass.getName().contains("com.examplepackage.accountpackage")) {
            checkTranscience(fieldClass);
        }
    }


class User {
    private String x;
    private List<String> stringList;
    private List<Account> accounts;
    private int y;
}

public static void main(){
    checkTranscience(User.class);
}

您可能需要稍微调整代码以获得特定结果,但我会将其留给用户。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM