Reputation: 1091
Iam currently trying to create a distinct List<Class> classList
which contains all Classes of an object for example
DemoObject.java
public class DemoObject {
private Integer id;
private String name;
private BigDecimal price;
private Boolean isActive;
private List<NestedDemoObject> nested;
}
NestedDemoObject.java
public class NestedDemoObject {
private Integer id;
private String nameNest;
private Boolean isActive;
}
What i want to create is a method public List<Class> getDistinctClasses(Class cl);
which you give as input for example DemoObject.class
and returns a list with
[DemoObject.class, Integer.class, String.class, BigDecimal.class, Boolean.class, List.class, NestedDemoObject.class]
Another example for NestedDemoObject.class
would be
[NestedDemoObject.class, Integer.class, String.class, Boolean.class]
I tried to use the .getDeclaredClasses()
from Class
without any luck.
There is any way to get all nested classes from an object with Reflection API?
Any help or direction appreciated.
Upvotes: 6
Views: 5642
Reputation: 7299
The solution provided by Mark is partially correct. You're on the right way trying to retrieve the classes from declared fields. However getType()
method does not reveal the generic types.
In order to access the generic types you should use Field.getGenericType()
instead. It returns the classes as Type
objects. The Field
objects DO KNOW their own types (they are not erased as one may believe mistakenly).
This is a java 1.8+ example printing the types with generics:
Arrays.stream(DemoObject.class.getDeclaredFields())
.map(Field::getGenericType)
.map(Type::getTypeName)
.distinct()
.forEach(System.out::println);
It will print the following result:
java.lang.Integer
java.lang.String
java.math.BigDecimal
java.lang.Boolean
java.util.List<com.eto.sandbox.NestedDemoObject>
If you want to play with generic types or parse them for any reason then you could use this example:
Arrays.stream(DemoObject.class.getDeclaredFields())
.map(Field::getGenericType)
.distinct()
.forEach(type -> {
if (type instanceof Class) {
// This is a simple class
} else if (type instanceof ParameterizedType) {
// This is a generic type. You can parse its parameters recursively.
}
});
Upvotes: 3
Reputation: 5239
Maybe this points you in the right direction:
for (Field f : DemoObject.class.getDeclaredFields()) {
System.out.println(f.getType().getName());
}
This prints:
java.lang.Integer
java.lang.String
java.math.BigDecimal
java.lang.Boolean
java.util.List
You can get a class instance through something like Class.forName
.
I find it odd that getDeclaredClasses
is not working for me either, and I will look into that. I'll update the answer when I know more.
UPDATE
getDeclaredClasses
prints classes defined inside a class like so:
class DemoObject {
private Integer id;
private String name;
private BigDecimal price;
private Boolean isActive;
private List<NestedDemoObject> nested;
public class InnerClass {
}
}
Then executing getDeclaredClasses
:
for (Class<?> f : DemoObject.class.getDeclaredClasses()) {
System.out.println(f.getName());
}
prints the value:
DemoObject$InnerClass
Upvotes: 3