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

如何在Java Lambda表达式中“固化”值?构建器场景问题

如何让每个Lambda表达式拥有独立的乘数函数?

问题代码

@FunctionalInterface
interface Callable {
    Integer multiply(Integer by);
}

class Builder {
    private Integer multiplier;

    public Builder multiplyBy(Integer multiplier) {
        this.multiplier= multiplier;
        return this;
    }

    public Callable build() {
        return (value) -> value * multiplier; // 如何"固化"当前值?
    }
}

// 调用代码
Builder builder = new Builder();
Callable multiplierBy3 = builder.multiplyBy(3).build();
Callable multiplierBy6 = builder.multiplyBy(6).build();

multiplierBy3.multiply(10); // 预期返回30,实际返回60
multiplierBy6.multiply(10); // 返回60,符合预期

问题原因

Lambda表达式捕获的是Builder实例中multiplier的引用,而非当前值。第二次调用multiplyBy(6)修改了同一个Builder实例的multiplier值,导致之前创建的multiplierBy3也会使用更新后的数值。

解决方案

方案1:捕获局部变量固化当前值

在build方法中,先将当前multiplier赋值给一个局部变量,让Lambda捕获这个局部变量(局部变量默认是等效final的,不会被后续修改):

public Callable build() {
    Integer currentMultiplier = this.multiplier; // 复制当前值到局部变量
    return (value) -> value * currentMultiplier;
}

方案2:让Builder成为不可变类,每次生成新实例

将Builder设计为不可变类,每次设置参数时返回新的Builder实例,从根源避免状态共享:

@FunctionalInterface
interface Callable {
    Integer multiply(Integer by);
}

class Builder {
    private final Integer multiplier; // 用final确保不可变

    // 私有构造器,只能通过静态方法创建实例
    private Builder(Integer multiplier) {
        this.multiplier = multiplier;
    }

    public static Builder multiplyBy(Integer multiplier) {
        return new Builder(multiplier);
    }

    public Callable build() {
        return (value) -> value * multiplier;
    }
}

// 调用方式调整为:
Callable multiplierBy3 = Builder.multiplyBy(3).build();
Callable multiplierBy6 = Builder.multiplyBy(6).build();

方案3:修改multiplyBy方法返回新实例

如果保留原有Builder的结构,修改multiplyBy方法,每次调用时创建新的Builder实例并设置参数,而非修改当前实例:

public Builder multiplyBy(Integer multiplier) {
    Builder newBuilder = new Builder();
    newBuilder.multiplier = multiplier;
    return newBuilder;
}

说明

方案1是最轻量化的修改,仅调整build方法即可;方案2从设计层面避免了状态共享,更符合不可变对象的设计原则,适合需要多次复用Builder的场景;方案3则是在原有API基础上做最小调整,保持链式调用的同时避免状态污染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:45:20