怎样利用Either和Option进行函数式错误处理的示例
发布时间:2021-02-04 11:30:21
来源:亿速云
阅读:86
作者:小新
这篇文章将为大家详细讲解有关怎样利用Either和Option进行函数式错误处理的示例,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
前言
我将讨论 Scala 风格的模式匹配,但首先我需要通过 Either 概念建立一些背景知识。Either 的其中一个用法是函数式风格的错误处理,我会在本期文章中对其进行介绍。
在 Java 中,错误的处理在传统上由异常以及创建和传播异常的语言支持进行。但是,如果不存在结构化异常处理又如何呢?许多函数式语言不支持异常范式,所以它们必须找到表达错误条件的替代方式。在本文中,我将演示 Java 中类型安全的错误处理机制,该机制绕过正常的异常传播机制(并通过 Functional Java 框架的一些示例协助说明)。
函数式错误处理
如果您想在 Java 中不使用异常来处理错误,最根本的障碍是语言的限制,因为方法只能返回单个值。但是,当然,方法可以 返回单个 Object(或子类)引用,其中可包含多个值。那么,我可以使用一个 Map 来启用多个返回值。请看看清单 1 中的 divide() 方法:
清单 1. 使用 Map 处理多个返回值public static Map divide(int x, int y) {
Map result = new HashMap();
if (y == 0)
result.put("exception", new Exception("div by zero"));
else
result.put("answer", (double) x / y);
return result;
}
在 清单 1 中,我创建了一个 Map,以 String 为键,并以 Object 为值。在 divide() 方法中,我输出 exception 来表示失败,或者输出 answer 来表示成功。清单 2 中对两种模式都进行了测试:
清单 2. 使用 Map 测试成功与失败@Test
public void maps_success() {
Map result = RomanNumeralParser.divide(4, 2);
assertEquals(2.0, (Double) result.get("answer"), 0.1);
}
@Test
public void maps_failure() {
Map result = RomanNumeralParser.divide(4, 0);
assertEquals("div by zero", ((Exception) result.get("exception")).getMessage());
}
在 清单 2 中,maps_success 测试验证在返回的 Map 中是否存在正确的条目。maps_failure 测试检查异常情况。
这种方法有一些明显的问题。首先,Map 中的结果无论如何都不是类型安全的,它禁用了编译器捕获特定错误的能力。键的枚举可以略微改善这种情况,但效果不大。其次,该方法调用器并不知道方法调用是否成功,这加重了调用程序的负担,它要检查可能结果的词典。第三,没有什么能阻止这两个键都有值,这使得结果模棱两可。
我需要的是一种让我能够以类型安全的方式返回两个(或多个)值的机制。
Either 类
返回两个不同值的需求经常出现在函数式语言中,用来模拟这种行为的一个常用数据结构是 Either 类。在 Java 中,我可以使用泛型创建一个简单的 Either 类,如清单 3 所示:
清单 3. 通过 Either 类返回两个(类型安全的)值public class Either {
private A left = null;
private B right = null;
private Either(A a,B b) {
left = a;
right = b;
}
public static Either left(A a) {
return new Either(a,null);
}
public A left() {
return left;