You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何将方法名作为参数传递以消除重复代码

是否存在方法名参数化的实现方案?

基础代码示例

public class JournalLine {
    BigDecimal ccyAmount;
    BigDecimal lcyAmount;
    BigDecimal rptAmount;
   
    // 省略Getters和Setters
}

原有冗余实现

原有三段求和逻辑结构完全一致,仅调用的getter方法不同,存在明显代码重复,且这类逻辑会在应用不同位置被调用,不一定同时出现:

// Calculate totals
BigDecimal totalCcyAmount = journalLines.stream()
                                        .map(journalLine -> journalLine.getCcyAmount())
                                        .reduce((a, b) -> a.add(b))
                                        .orElse(BigDecimal.ZERO);

BigDecimal totalLclAmount = journalLines.stream()
                                       .map(journalLine -> journalLine.getLclAmount())
                                       .reduce((a, b) -> a.add(b))
                                       .orElse(BigDecimal.ZERO);

BigDecimal totalRptAmount = journalLines.stream()
                                        .map(journalLine -> journalLine.getRptAmount())
                                        .reduce((a, b) -> a.add(b))
                                        .orElse(BigDecimal.ZERO);

期望实现目标

希望通过传入方法标识的方式抽取通用求和逻辑,减少重复代码,期望调用形式如下:

//Calculate totals and pass the method name
BigDecimal totalCcyAmount = getTotal(journalLines, "getCcyAmount");
BigDecimal totalLclAmount = getTotal(journalLines, "getLclAmount");
BigDecimal totalRptAmount = getTotal(journalLines, "getRptAmount");
                                        
public BigDecimal getTotal( List<JournalLine> journalLines, String METHOD_NAME) {
    return journalLines.stream()
                         .map(journalLine -> journalLine.METHOD_NAME)
                         .reduce((a, b) -> a.add(b))
                         .orElse(BigDecimal.ZERO);
}

推荐实现方案

不建议使用字符串传方法名+反射的实现方式,这种方案没有编译期校验,方法名写错、返回值不匹配都要到运行时才会抛错,后续重构字段名时字符串参数不会被同步修改,很容易出隐蔽bug,还有额外的反射性能开销。

Java 8及以上版本直接用函数式接口+方法引用实现即可,完全满足消除代码重复的需求,同时保证类型安全:

import java.math.BigDecimal;
import java.util.List;
import java.util.function.Function;

// 通用求和方法
public BigDecimal getTotal(List<JournalLine> journalLines, Function<JournalLine, BigDecimal> amountExtractor) {
    return journalLines.stream()
                       .map(amountExtractor)
                       .reduce(BigDecimal::add)
                       .orElse(BigDecimal.ZERO);
}

// 调用方式
BigDecimal totalCcyAmount = getTotal(journalLines, JournalLine::getCcyAmount);
BigDecimal totalLclAmount = getTotal(journalLines, JournalLine::getLclAmount);
BigDecimal totalRptAmount = getTotal(journalLines, JournalLine::getRptAmount);

如果后续需要对其他实体类的BigDecimal字段求和,还可以把方法改成泛型版本,通用性更强:

public <T> BigDecimal getTotal(List<T> list, Function<T, BigDecimal> amountExtractor) {
    return list.stream()
               .map(amountExtractor)
               .reduce(BigDecimal::add)
               .orElse(BigDecimal.ZERO);
}

反射实现(不推荐)

风险提示:反射实现方案无编译期校验、可维护性差、存在额外性能开销,仅适合必须动态传入方法名字符串的极端场景,常规业务开发优先选择函数式接口方案。

如果确实有动态传入方法名字符串的特殊需求,可以通过反射实现:

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.List;

public BigDecimal getTotalByMethodName(List<JournalLine> journalLines, String methodName) {
    try {
        Method getterMethod = JournalLine.class.getMethod(methodName);
        return journalLines.stream()
                           .map(line -> {
                               try {
                                   Object result = getterMethod.invoke(line);
                                   if (!(result instanceof BigDecimal)) {
                                       throw new IllegalStateException("方法" + methodName + "返回值不是BigDecimal类型");
                                   }
                                   return (BigDecimal) result;
                               } catch (Exception e) {
                                   throw new RuntimeException("调用字段getter失败", e);
                               }
                           })
                           .reduce(BigDecimal::add)
                           .orElse(BigDecimal.ZERO);
    } catch (NoSuchMethodException e) {
        throw new IllegalArgumentException("JournalLine类不存在无参方法:" + methodName, e);
    }
}

内容的提问来源于stack exchange,提问作者Dimitri Dewaele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:12:18