'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
likeCollection.class.isAssignableFrom(List.class)
to check modifiers of field like
transient
useModifier.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 viafield.setAccessible(true)
. Then if you are sure about what type of objectvalue
holds you can cast it to that type likeList<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.)
- Loop through the fields in User.
- For fields with predefined types check transcience.
- 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 |