用 scala 有一年多了, 对于 scala 中的 Option 和 Try 使用的较为频繁, 对其应用场景相对熟悉一些. 而对于 Either, 仔细回想一下却发现几乎 (完全) 没有使用过, 其实并不是没有遇到过 Either 的使用场景, 只是遇到的时候不知道能够使用 Either 来解决此问题.
昨天在网上偶然看到一篇介绍 Either 的文章, 发现有一种场景可以使用 Either 来解决, 具体是这样的:
web 系统中, Controller 层调用 service 层方法, 根据邮箱查询注册的用户 User, 如果未取到 User, 则需要知道是什么原因导致的.
定义一个方法, 根据登录邮箱查询 User 对象, 方法签名如: def getUserByEmail(email:String):User
注意方法的返回值类型, 这里返回的是 User 对象. 在运行时会发生如下三种情况:
1, 正常返回 null
2, 正常返回 User
3, 发生异常抛出 Exception.
对于情况 1, 调用处如果想知道是为什么返回了 null, 是因为 email 的格式错误? 还是因为该 email 没有注册的用户? 该种方法签名是没办法把失败原因返回给调用处的 .
那么我们考虑能否把返回结果类型 User 修改为 Try[User], 即: def getUserByEmail(email:String):Try[User]
对于刚才的情况 1, 如果是因为 email 格式不对, 我们在方法体内可以封装一个 Failure(RuntimeException("邮箱格式错误"))返回给调用处. 而如果是该邮箱未注册, 未查询到该用户, 如果再封装一个 Exception 就不合适了. 因为查不到用户属于正常的逻辑, 不属于异常范畴, 这种方式是不可取的.
那么我们再考虑把返回值类型 Try[User]修改为 Option[User], 即: def getUserByEmail(email:String):Option[User]
这样, 只是把把返回结果 null 修改为 None, 并未达到我们想要的目的
这时, 我们就可以考虑把返回值类型修改为 Either[String,User], 即: def getUserByEmail(email:String):Either[String,User].
如果查询到 User, 那么返回一个 Right(user)即可, 如果邮箱格式错误, 则返回一个 Left("邮箱格式错误"), 如果该邮箱未进行注册, 则返回 Left("该邮箱未进行注册"); 如果运行中发生 Exception, 可以直接抛出, 也可以封装为 Left("发生 XXX 异常")返回给调用处.
除了通过 Either 来返回失败信息, 我们也可以使用 Tuple2[String,User]类型来实现想要的结果, 在失败的时候返回 Tuple2("失败原因描述",null), 只是相对于 Either 来说, 不是那么便捷.
使用方式可见如下伪代码:
- @Test
- def testEither(): Unit = {
- getUserByEmail("xxx@sina.com") match {
- case Right(user) => ???
- case Left(msg) => println("查询用户失败, 原因:" + msg)
- }
- }
- def getUserByEmail(email: String): Either[String, User] = {
- if (email 无效) {
- return Left("邮箱格式错误")
- } else {
- if (未查询到注册邮箱) {
- return Left("该用户不存在")
- } else {
- return Right(user)
- }
- }
- }
- =========================================
- =========================================
- -------end
来源: https://www.cnblogs.com/PerkinsZhu/p/9450593.html