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

Builder模式疑问:ConcreteRequest#getLocalValue不可访问但build可用的原因

问题分析与解决

核心原因

这大概率是因为你的Builder类的方法返回类型没有正确适配子类。举个典型的错误实现场景:

// 父类Builder
public abstract class AbstractRequestBuilder {
    protected String globalValue;

    public AbstractRequestBuilder globalValue(String globalValue) {
        this.globalValue = globalValue;
        return this;
    }

    public AbstractRequest build() {
        AbstractRequest request = new AbstractRequest();
        request.setGlobalValue(globalValue);
        return request;
    }
}

// 子类Builder
public class ConcreteRequestBuilder extends AbstractRequestBuilder {
    private String localValue;

    public ConcreteRequestBuilder localValue(String localValue) {
        this.localValue = localValue;
        return this;
    }

    @Override
    public ConcreteRequest build() {
        ConcreteRequest request = new ConcreteRequest();
        request.setGlobalValue(globalValue);
        request.setLocalValue(localValue);
        return request;
    }
}

如果调用时是这样:

ConcreteRequest request = new ConcreteRequestBuilder()
    .globalValue("test") // 这里返回的是AbstractRequestBuilder类型
    .localValue("local") // 编译报错,因为父类Builder没有这个方法
    .build();

build能正常使用,是因为你在子类Builder里覆写了build方法,返回ConcreteRequest类型;但父类的通用参数方法返回的是父类Builder类型,导致链式调用中途类型降级,找不到子类的localValue方法。

正确实现方式

用泛型自限定保证父类Builder方法返回子类Builder类型:

// 父类Builder,使用泛型自限定
public abstract class AbstractRequestBuilder<T extends AbstractRequestBuilder<T>> {
    protected String globalValue;

    @SuppressWarnings("unchecked")
    public T globalValue(String globalValue) {
        this.globalValue = globalValue;
        return (T) this;
    }

    public abstract AbstractRequest build();
}

// 子类Builder,指定泛型参数为自身
public class ConcreteRequestBuilder extends AbstractRequestBuilder<ConcreteRequestBuilder> {
    private String localValue;

    public ConcreteRequestBuilder localValue(String localValue) {
        this.localValue = localValue;
        return this;
    }

    @Override
    public ConcreteRequest build() {
        ConcreteRequest request = new ConcreteRequest();
        request.setGlobalValue(globalValue);
        request.setLocalValue(localValue);
        return request;
    }
}

这样链式调用的类型始终是ConcreteRequestBuilder,就能正常访问localValue方法:

ConcreteRequest request = new ConcreteRequestBuilder()
    .globalValue("test")
    .localValue("local")
    .build();

额外注意点

  • DTO类的继承关系要和Builder类的继承对应,保证泛型绑定正确。
  • 父类Builder尽量用抽象方法定义build,由子类实现具体的DTO实例化逻辑,避免类型不匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:01:05