'How to iterate Field of type List using java reflection

I have a class called User which is having List of Account class objects like this

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

The Account object is having one transient field which i want to find and do some thing with that

public class Account{
  private transient openDateInOrgDateFormat;
}

This field i want to find using reflection and then check whether its transient then do something. Through reflection how to find field of type collection and then iterate that and to find if field inside the object which is in the list is transient or not.



Solution 1:[1]

Since I don't know what exactly is stopping you from writing your code here are some tools which should be helpful:

  • to get array of fields declared in class use

    Field[] fields = User.class.getDeclaredFields()
    
  • to check what is the type assigned to field use field.getType().

  • to check if type is same as other type like List simply use

    type.equals(List.class);
    
  • to check if one type belongs to family of some ancestor (like List is subtype of Collection) use isAssignableFrom like

    Collection.class.isAssignableFrom(List.class)
    
  • to check modifiers of field like transient use

    Modifier.isTransient(field.getModifiers())
    
  • to access value held by field in specific instance, use

    Object value = field.get(instanceWithThatField)
    

    but in case of private fields you will need to make it accessible first via field.setAccessible(true). Then if you are sure about what type of object value holds you can cast it to that type like

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

    or do both operations in one line, like in your case

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

    which you can later iterate the way you want like
    for(Account acc : list){ /*handle each acc*/ }

Solution 2:[2]

You can do it with arrays stream:

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

Solution 3:[3]

Elaborating on @Pshemo's answer, Here are the steps: (Please note its easier to get specific Type parameters from a Class than an Object, due to Type erasures.)

  1. Loop through the fields in User.
  2. For fields with predefined types check transcience.
  3. For Collections, get the type of of its parameter and if its a custom Type, run a recursion on that class.

e.g

    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);
}

You might have to tune the code a bit to get the specific result, but I'll leave that to the user.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Daniel
Solution 3