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

Java Vavr如何固定Either左侧类型定义Result<T>简化方法签名

实现方案

Vavr 的 Either 是封闭抽象类型,本身不允许自定义子类直接继承,不需要强行继承 Either,通过包装 Either<Error, T> 的方式实现 Result<T>,即可保留 Either 的全部流式操作能力,也不需要额外编写冗余业务逻辑实现。

示例代码

1. 定义 Result 类

import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.control.Either;
import java.util.function.Function;
import java.util.function.Supplier;

public final class Result<T> {
    private final Either<Error, T> delegate;

    // 私有构造方法,禁止外部直接实例化
    private Result(Either<Error, T> delegate) {
        this.delegate = delegate;
    }

    // 工厂方法:构造成功的Result
    public static <T> Result<T> ok(T value) {
        return new Result<>(Either.right(value));
    }

    // 工厂方法:构造失败的Result
    public static <T> Result<T> err(Error error) {
        return new Result<>(Either.left(error));
    }

    // 代理Either的核心流式方法,保持和Either一致的使用体验
    public <U> Result<U> map(Function<? super T, ? extends U> mapper) {
        return new Result<>(delegate.map(mapper));
    }

    public <U> Result<U> flatMap(Function<? super T, ? extends Result<? extends U>> mapper) {
        return new Result<>(delegate.flatMap(val -> mapper.apply(val).delegate));
    }

    public T orElse(T fallback) {
        return delegate.getOrElse(fallback);
    }

    public T orElseGet(Supplier<? extends T> supplier) {
        return delegate.getOrElseGet(supplier);
    }

    public <E extends Throwable> T orElseThrow(Function<? super Error, E> exceptionMapper) throws E {
        return delegate.getOrElseThrow(exceptionMapper);
    }

    public boolean isOk() {
        return delegate.isRight();
    }

    public boolean isErr() {
        return delegate.isLeft();
    }

    public Error getErr() {
        return delegate.getLeft();
    }

    public T get() {
        return delegate.get();
    }

    // 适配流处理的fold方法
    public <U> U fold(Function<Error, U> errMapper, Function<T, U> okMapper) {
        return delegate.fold(errMapper, okMapper);
    }

    // 可按需暴露原生Either做扩展操作
    public Either<Error, T> toEither() {
        return delegate;
    }
}

2. 业务方法使用示例

直接实现你需要的简化方法签名:

// 不需要每次重复写Either<Error, xxx>
public Result<Employee> processEmployee(Employee e) {
    if (e.getId() == null) {
        return Result.err(new Error("员工ID不能为空"));
    }
    // 业务处理逻辑
    return Result.ok(e);
}

3. 流处理调用示例

完全保留Vavr的链式调用能力,写法和原生Either一致,语义更清晰:

List<Employee> employees = ...;
List<Tuple2<Employee, String>> processedResults = employees.stream()
    .map(this::processEmployee)
    .map(result -> result.fold(
        err -> Tuple.of(null, err.getMessage()),
        ok -> Tuple.of(ok, "处理成功")
    ))
    .toList();

方案说明

Vavr 的 Either 设计为 sealed 类型,仅允许内部的 Left 和 Right 两个实现类继承,外部自定义子类会直接编译报错,上述包装代理是最轻量化的实现方案,所有核心逻辑都代理给内部的 Either 实例,完全满足简化签名和流式调用的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 23:06:07