【问题标题】:How to iterate Field of type List using java reflection如何使用java反射迭代List类型的字段
【发布时间】:2016-10-14 13:06:41
【问题描述】:

我有一个名为 User 的类,它有这样的 Account 类对象列表

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

Account 对象有一个临时字段,我想找到它并用它做一些事情

public class Account{
  private transient openDateInOrgDateFormat;
}

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

【问题讨论】:

  • 查看java reflection trail,他们甚至有一个适合您需求的示例。
  • 您的标题问题专门来自 List,但后来您要求“类型集合的字段”。那么它是哪个,List 或任何 Collection,如 List、Set 或其他?还有究竟是什么阻止你编写代码?您对哪一步有问题?
  • (field.getModifiers() &amp;&amp; Modifier.TRANSIENT) != 0 检查该字段是否为临时字段。
  • @talex 是&amp; 而不是&amp;&amp;

标签: java reflection


【解决方案1】:

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

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

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

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

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

    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*/ }

【讨论】:

  • 基本上我的问题是如果 Field 是列表类型,那么如何将 Field 类型转换为 Collection 并使用反射进行迭代。
  • @PracheerPancholi 您没有将字段类型转换为集合。您需要获取某个 User 对象中保存的字段的值。所以就像上一点提到的,你需要使用field.setAccessible(true); Object value = field.get(userObject);。然后您可以尝试将value 转换为Collection 或其他适合value 引用所持有对象的类型。
  • 感谢这回答了我的问题。请修改答案以便我接受。
  • @PracheerPancholi 检查您是否是这个意思。
  • @PracheerPancholi 在您的示例中,User 持有 List&lt;Account&gt; accounts,但不同的用户将持有不同的帐户。因此,当我们编写类似user1.getAccouts() 的内容时,我们将得到与通过user2.getAccounts() 返回的列表不同的列表。 Field 不受任何特定实例的限制,但它代表类结构的一部分。因此,如果您想使用 Field 对象,您需要告诉它应该从哪个用户那里读取并返回它。因此,如果您想从 user1 获取帐户,例如 user1.getAccounts(),则需要 accountsField.get(user1)(其中 accountsFieldField)。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    相关资源
    最近更新 更多