【问题标题】:How to use a lis of parameterized property names and type for a java bean如何使用 Java bean 的参数化属性名称和类型列表
【发布时间】:2011-08-04 03:31:44
【问题描述】:

说我有一颗豆子

public class SomeBean{
     List<String> messages;
     List<Integer> scores;
     String id;
     int  number;

.... }

我正在使用以下代码来处理或转储属性

        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());

        }

我希望能够获得“分数”和“消息”的参数化类型。 当我破坏代码时,“descriptor.getPropertyType().getName()”的值对于消息和分数都是“java.util.List”。

如何判断“消息”的属性描述符是指List&lt;String&gt;,而“分数”的属性描述符是指List&lt;Integer&gt;

【问题讨论】:

    标签: java generics reflection introspection propertydescriptor


    【解决方案1】:

    有两种情况。

    第一种情况是在编译时不知道属性的参数化类型:

    public class Pair<A, B> {
      public A getFirst() { ... }
      public B getSecond() { ... }
    }
    

    在这种情况下,您无法在编译时知道,这就是 @darioo 所说的。

    第二种情况是你的,当属性的类型参数在运行时是已知的。下面的代码应该可以帮助您准确地确定您想要做什么:

    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);
            }
        }
    }
    

    这里的关键是获取read或者write方法,分别使用API​​Method.getGenericReturnType()或者Method.getParameterTypes()

    请注意,处理java.lang.reflect.Type 通常会变得非常乏味/棘手,例如:

    public Map<Nation, Map<A extends PostCode, B extends Location>> getGlobalPostCodes() { ... }
    

    【讨论】:

      【解决方案2】:

      只要字段具有完全指定的编译时类型,如您的示例(List&lt;String&gt; 而不是List&lt;T&gt;,即),您就可以使用反射来获取此信息:

      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));
        }
      }
      

      不确定是否可以使用与 bean 相关的代码来执行此操作,但看起来可以。

      【讨论】:

      • 我知道使用 Field[] f= class.getDeclaredFields() 这是可能的,但问题是它不会继承字段。并且在递归遍历所有父类时变得非常混乱。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      • 2012-04-12
      • 2020-01-25
      • 1970-01-01
      • 2013-12-06
      相关资源
      最近更新 更多