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

Vavr中Either flatMap类型混淆编译错误排查求助

问题:Vavr Either.flatMap 类型推断失败导致编译错误

使用Vavr的Either进行链式操作时,调用flatMap方法出现编译错误,提示无法推断类型变量U。手动编写业务代码和IntelliJ自动生成的Function均无法编译,明明U应为Department类型却报错,需排查原因及解决方法。

原业务代码

@Override
public Either<? extends ApplicationError, Department> createDepartment(CreateDepartmentCommand command) {
    Either<? extends ApplicationError, Department> department = Department.create(command.id(), command.name());
    Either<? extends ApplicationError, Department> createdDepartment = department.flatMap((Department dep) -> {
        Optional<Department> existingDepartment = getDepartmentDrivenPort.getByName(command.name());
        if (existingDepartment.isPresent()) {
            Either<? extends ApplicationError, Department> left = Either.left(new DepartmentExistsError());
            return left;
        } else {
            Either<? extends ApplicationError, Department> right = createDepartmentDrivenPort.create(dep);
            return right;
        }
    });        
     
    return createdDepartment;
}

编译错误信息

java: method flatMap in interface io.vavr.control.Either<L,R> cannot be applied to given types;
  required: java.util.function.Function<? super com.codependent.hexapp.application.domain.Department,? extends io.vavr.control.Either<capture#1 of ? extends com.codependent.hexapp.application.domain.error.ApplicationError,? extends U>>
  found:    (Departmen[...]; } }
  reason: cannot infer type-variable(s) U
    (argument mismatch; bad return type in lambda expression
      io.vavr.control.Either<capture#2 of ? extends com.codependent.hexapp.application.domain.error.ApplicationError,com.codependent.hexapp.application.domain.Department> cannot be converted to io.vavr.control.Either<capture#1 of ? extends com.codependent.hexapp.application.domain.error.ApplicationError,? extends U>)

IntelliJ自动生成的Function代码及错误

自动生成代码

department.flatMap(new Function<Department, Either<? extends ApplicationError, ?>>() {
    @Override
    public Either<? extends ApplicationError, ?> apply(Department department) {
        return null;
    }
});

对应编译错误

java: method flatMap in interface io.vavr.control.Either<L,R> cannot be applied to given types;
  required: java.util.function.Function<? super com.codependent.hexapp.application.domain.Department,? extends io.vavr.control.Either<capture#1 of ? extends com.codependent.hexapp.application.domain.error.ApplicationError,? extends U>>
  found:    <anonymous java.util.function.Function<com.codependent.hexapp.application.domain.Department,io.vavr.control.Either<? extends com.codependent.hexapp.application.domain.error.ApplicationError,?>>>
  reason: cannot infer type-variable(s) U
    (argument mis

原因分析

核心问题是使用了通配符? extends ApplicationError作为Either的左类型,导致Java编译器无法确定具体的类型边界。Vavr的flatMap要求返回的Either左类型必须与原Either的左类型兼容,而通配符带来的类型不确定性让编译器无法推断出U的具体类型。

解决方法

方法1:替换通配符为具体错误类型

将Either的左类型从? extends ApplicationError改为ApplicationError(所有错误子类都可向上转型为该类型),让编译器明确类型边界:

@Override
public Either<ApplicationError, Department> createDepartment(CreateDepartmentCommand command) {
    Either<ApplicationError, Department> department = Department.create(command.id(), command.name());
    Either<ApplicationError, Department> createdDepartment = department.flatMap(dep -> {
        Optional<Department> existingDepartment = getDepartmentDrivenPort.getByName(command.name());
        if (existingDepartment.isPresent()) {
            return Either.left(new DepartmentExistsError());
        } else {
            return createDepartmentDrivenPort.create(dep);
        }
    });        
     
    return createdDepartment;
}

方法2:显式指定flatMap的类型参数

如果必须保留通配符,可以显式指定flatMap的泛型参数,帮助编译器推断:

Either<? extends ApplicationError, Department> createdDepartment = department.<ApplicationError, Department>flatMap(dep -> {
    Optional<Department> existingDepartment = getDepartmentDrivenPort.getByName(command.name());
    if (existingDepartment.isPresent()) {
        return Either.left(new DepartmentExistsError());
    } else {
        return createDepartmentDrivenPort.create(dep);
    }
});

推荐使用方法1,避免通配符带来的类型模糊问题,使代码更简洁易读。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:47:50