java无内置either类型,但可通过vavr等库或自定义实现将受检异常转为left/right值,使其成为可传递、组合、恢复的一等公民,避免中断流式处理。

Java 本身没有内置 Either 类型,但通过引入第三方库(如 Vavr、Cyclops 或自定义轻量实现),可以将受检异常“转为值”,从而绕过函数式接口对 throws 的编译限制——不是掩盖异常,而是把它变成流中可传递、可组合、可恢复的数据。
Either 是什么:左值表示失败,右值表示成功
Either<e r></e> 是一个二元容器:左侧(Left)存异常或错误信息,右侧(Right)存正常计算结果。它让异常不再打断执行链,而是成为 Stream 或 Optional 那样的“一等公民”。
- 调用可能抛受检异常的方法时,不直接 throw,而是返回
Either<ioexception string></ioexception> - 后续操作可用
map、flatMap、peek等函数式方法安全处理成功路径 - 失败路径可通过
leftMap、onLeft统一记录、转换或降级,不侵入业务逻辑
用 Vavr 的 Either 替代 try-catch 块
Vavr(原 Javaslang)提供开箱即用的 io.vavr.control.Either,配合其 CheckedFunction 接口,能自然承载受检异常:
// 定义可抛 IOException 的函数
CheckedFunction<string string> readFile = path -> Files.readString(Paths.get(path));
// 转为 Either:成功 → Right,异常 → Left
List<either string>> results = paths.stream()
.map(path -> Try.of(() -> readFile.apply(path)).toEither())
.collect(Collectors.toList());
// 分别处理成功与失败
results.forEach(either -> {
either.fold(
error -> LOG.error("读取失败: {}", path, error),
content -> process(content)
);
});</either></string>
这里没写一行 try/catch,也没把 IOException 包装成 RuntimeException,异常语义完整保留,且可延迟决策如何响应。
自定义简易 Either + CheckedFunction 工具类
若项目不能引入 Vavr,可手写最小可用版本:
public interface CheckedFunction<t r> {
R apply(T t) throws Exception;
}
public static <t r e extends exception> Function<t either r>> lift(CheckedFunction<t r> f) {
return t -> {
try {
return Either.right(f.apply(t));
} catch (Exception e) {
return Either.left((E) e);
}
};
}</t></t></t></t>
使用时:
Function<string either string>> safeReader = lift(Files::readString);</string>- 传入
Stream.map(safeReader)完全合法,不会编译报错 - 后续用
.filter(Either::isRight).map(Either::get)提取成功值,或用.map(e -> e.isLeft() ? handle(e.getLeft()) : e.getRight())统一分支
和 RuntimeException 包装方案的本质区别
关键不在“能不能跑”,而在“异常是否还参与流程控制”:
-
包装成 RuntimeException:异常被“扔出”,调用链中断,只能靠外层
try捕获,无法在 Stream 中跳过单个失败项继续处理其余元素 - 转为 Either:异常是数据,可 map、filter、collect、合并、重试——比如对一批文件读取,失败的记录进 error log,成功的继续解析,全程保持函数式风格
- 适合场景:批量作业、ETL 流程、配置加载、API 批量调用等需容错与可观测性的场合
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











