How to use a lis of parameterized property names and type for a java bean
Say I have a bean
public class SomeBean{
List<String> messages;
List<Integer> scores;
String id;
int number;
.... }
I am using the following code to process or dump the propreties
BeanInfo beanInfo = Introspector.getBeanInfo(beanClass, Object.class);
PropertyDescriptor descriptors[] = beanInfo.getPropertyDescriptors();
int stop = descriptors.length;
for (int i = 0; i < stop; ++i) {
PropertyDescriptor descriptor = descriptors[i];
logger.info(descriptor.getName() + " : " + descriptor.getPropertyType().getName() + ", writemethod :" + descriptor.getWriteMethod());
}
T开发者_开发技巧hat I want to be able to get the parameterized type for the "scores" and "messages". When I ruin the code, the value for the " descriptor.getPropertyType().getName()" is "java.util.List" for both messages and scores .
How do I tell if the property descriptor for "message" is referring to List<String>
and for "scores" is referring to List<Integer>
?
There are two cases.
The first case is when the property's parameterized type is not known at compile time:
public class Pair<A, B> {
public A getFirst() { ... }
public B getSecond() { ... }
}
In this case, you cannot know at compile time, and is what @darioo is talking about.
The second case is yours, when the properties' type parameters are known at runtime. The code below should help you figure out exactly what you want to do:
BeanInfo beanInfo = Introspector.getBeanInfo(beanClass, Object.class);
PropertyDescriptor descriptors[] = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor d : descriptors) {
final Type type = d.getReadMethod().getGenericReturnType();
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
System.out.println(d.getDisplayName());
for (Type atp : pt.getActualTypeArguments()) {
System.out.println(" " + atp);
}
}
}
The key here is to get the read or write method, and use the API Method.getGenericReturnType()
or Method.getParameterTypes()
respectively.
Note that dealing with java.lang.reflect.Type
generically gets quite tedious/tricky, consider, for example:
public Map<Nation, Map<A extends PostCode, B extends Location>> getGlobalPostCodes() { ... }
As long as the fields have fully specified compile-time types like in your example (List<String>
and not something like List<T>
, that is) you can use reflection to get this information:
for (Field field : SomeBean.class.getDeclaredFields()) {
Type type = field.getGenericType();
System.out.println(field.getName() + ": " + type);
if (type instanceof ParameterizedType) {
ParameterizedType parameterized = (ParameterizedType) type;
Type raw = parameterized.getRawType(); // This would be Class<List>, say
Type[] typeArgs = parameterized.getActualTypeArguments();
System.out.println(Arrays.toString(typeArgs));
}
}
Wasn't sure if you could do this with the bean-related code, but it looks like you can.
精彩评论