'Iterating through multiple subclasses and attempting to get the value of each field. java.lang.IllegalArgumentException: Can't set XXX field XX to XXX
I am trying to iterate through every subclass of a class and get the value of every field for each of them. I have successfully gotten every subclass with a ClassPathScanningCandidateComponentProvider object and can also look at every field.
This works as expected:
try {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
false);
provider.addIncludeFilter(new AssignableTypeFilter(Resource.class));
Set<BeanDefinition> components =
provider.findCandidateComponents("com/availaboard/engine/resource");
for (BeanDefinition component : components) {
Class<?> cls = Class.forName(component.getBeanClassName());
System.out.println("Class: " + cls);
for (Field field : cls.getDeclaredFields()) {
field.setAccessible(true);
System.out.println("Field: " + field);
System.out.println("Field Type: " + field.getType());
}
}
Output:
Class: class com.availaboard.engine.resource.Equipment
Class: class com.availaboard.engine.resource.Resource
Field: private java.lang.String com.availaboard.engine.resource.Resource.name
Field Type: class java.lang.String
Field: private com.availaboard.engine.resource.Status com.availaboard.engine.resource.Resource.status
Field Type: class com.availaboard.engine.resource.Status
Field: private int com.availaboard.engine.resource.Resource.id
Field Type: int
Class: class com.availaboard.engine.resource.Room
Class: class com.availaboard.engine.resource.User
Field: private java.lang.String com.availaboard.engine.resource.User.firstName
Field Type: class java.lang.String
Field: private java.lang.String com.availaboard.engine.resource.User.lastName
Field Type: class java.lang.String
Field: private java.lang.String com.availaboard.engine.resource.User.email
Field Type: class java.lang.String
Field: private java.lang.String com.availaboard.engine.resource.User.username
Field Type: class java.lang.String
Field: private java.lang.String com.availaboard.engine.resource.User.password
Field Type: class java.lang.String
The problem is when I try to get the value of a field. Since none of the fields are set it should return null. field.get(field.getType()) But instead now the program throws an error.
Class: class com.availaboard.engine.resource.Equipment
Class: class com.availaboard.engine.resource.Resource
Field: private java.lang.String com.availaboard.engine.resource.Resource.name
Field Type: class java.lang.String
java.lang.IllegalArgumentException: Can not set java.lang.String field com.availaboard.engine.resource.Resource.name to java.lang.Class
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
The error occurs right after it get's the first field of the Resource object because that is the first Object that has fields.
I have also tried passing the class in to the field.get() method: field.get(cls) But it still gives the same exception. Thoughts?
Solution 1:[1]
For those of you in the future who need help here’s my answer:
public <E extends Resource> void printClass(int ID, Class<E> type) {
try {
Resource res = (Resource) Class.forName(type.getName()).getConstructor().newInstance();
for (Field field : res.getClass().getDeclaredFields()) {
field.setAccessible(true);
System.out.println("Field: " + field);
System.out.println("Field Type: " + field.getType());
field.set(res, "test");
System.out.println("Field Value: " + field.get(res));
}
}
I basically just created a new instance of the class with class.forName and set it to the superclass of the class it has to come from, Resource
Solution 2:[2]
What I understood is you are trying to set a String while setting the parameter, but the column is of type Resource. field (reference variable) is a field of class Resource. Therefore, it can only get the fields from objects that are instances of Resource or subclasses. The object you're trying to get the field from is a Class object. Replace that cls with an instance of Resource and it'll work.
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 | Sam |
| Solution 2 | Bohemian |
