在Java中的流中间操作中使用Reflection

public class A {
    private List<B> listOfB = new LinkedList<>();
    //getter setters
}


public class B {
        private BigDecimal fieldOne;
        //8 more BigDecimal fields like this...
        private BigDecimal fieldTen;
        //getter setters
    }

我有一个A对象的列表,我的目标是获取B对象的每个字段的总和,以将其显示在JSF页面上。

最初,我想在A类中编写10个方法,例如getSumOfFieldOne()... getSumOfFieldTen()等。然后,我认为也许可以有一种更短的方法。

我尝试使用反射:

  public BigDecimal getSumOfField(String fieldName) throws Exception {
        Method getter = A.class.getMethod(String.format("get%s", StringUtils.capitalize(fieldName)));
        return getListOfB().stream()
               .map((BigDecimal)getter.invoke(A.class))
               .reduce(BigDecimal.ZERO, (d1, d2) -> d1.add(d2));
    }

在JSF页面上:

 <h:outputText value="#{theController.listOfA.getSumOfField('fieldOne')}"/>
  ...
 <h:outputText value="#{theController.listOfA.getSumOfField('fieldTen')}"/>

But it was not successful at compile time due to .map((BigDecimal)getter.invoke(A.class)) in getSumOfField

我通常在其他情况下使用的另一种选择是为每个字段编写10个方法或在A类的映射中收集这些字段的总和。但我想尝试一下反射方式,因为它更有趣且更具挑战性。请你帮助我好吗?

提前致谢。

评论
  • 碧鲁翠梅
    碧鲁翠梅 回复

    The clutter there is actually caused by exception handling for the call of invoke. The other part that you've missed is that the map accepts a Function such that you could still do:

    return getListOfB().stream()
            .map(b -> {
                try {
                    return (BigDecimal) getter.invoke(A.class);
                } catch (IllegalAccessException | InvocationTargetException e) { // poor
                    e.printStackTrace();
                    return BigDecimal.ZERO; // undefined in your code
                }
            })
            .reduce(BigDecimal.ZERO, BigDecimal::add);