I have a generic class as below, two type variables with three fields declared.
class RowClass<T1, T2> {
public T1 t1;
public T2 t2;
public T1 t3;
}
Now I want to extract a mapping as this:
t1 -> T1; t2 -> T2; t3 -> T3
So I can know exactly which type variable each field is associated to. Below code will not work as generic erasure.
for (Field declaredField : RowClass.class.getDeclaredFields()) {
System.out.println(declaredField.getName()+" -> " +declaredField.getType());
}
// t1 -> class java.lang.Object
// t2 -> class java.lang.Object
// t3 -> class java.lang.Object
// no type variable symbol printed
Why I ask this issue? Just for study, I am try to understand how Jackson deserialize json string to Class with declared generic type, sucn as List<String>
.
first, I can get the type variable list:
// the list of type variable
final TypeVariable<Class<RowClass>>[] typeParameters = RowClass.class.getTypeParameters();
Arrays.stream(typeParameters).forEach(System.out::println);
Second, I can also get the list of actual arguments:
class RowClassImpl extends RowClass<String, Integer> {
}
final ParameterizedType parameterizedType = (ParameterizedType) (RowClassImpl.class.getGenericSuperclass());
Arrays.stream(parameterizedType.getActualTypeArguments()).forEach(type -> System.out.println(type.getTypeName()));
If I can get the type variable vs field mapping, I can preserve all the generic information for each field.
"... Now I want to extract a mapping as this:
t1 -> T1; t2 -> T2; t3 -> T3 ..."
You wrote that incorrectly, by the way. It should be T1 for t3.
Here is an example.
RowClass<?, ?> r = new RowClass<>();
Map<String, Type> m
= Stream.of(r.getClass().getDeclaredFields())
.collect(Collectors.toMap(Field::getName, Field::getGenericType));
Output
{t1=T1, t2=T2, t3=T1}