Scala技术问题:无法从Future返回None及代码编译失败原因
核心原因其实是类型不匹配。Future[T]代表的是一个会异步产出T类型值的计算,如果你的方法声明返回Future[Int],那它最终必须生成一个Int类型的值——但None是Option类型的实例(具体是Option[Nothing]),它和Int完全是两个不同的类型,自然没法直接返回。
如果你的场景确实需要表示“异步操作可能没有结果”,正确的做法是把返回类型改成Future[Option[Int]]。这样你就可以在异步计算里返回Some(123)或者None,类型就能完美匹配了。
咱们把你的代码拆开来分析,有两个关键的编译错误:
错误1:Future与Option的类型混淆
你写了这样一行代码:
val f1:Option[Int] = Future{ None }
这里完全搞混了Future和Option的类型!Future{ None }返回的是Future[Option[Nothing]](因为None本质是Option[Nothing]的实例),但你却试图把它赋值给Option[Int]类型的变量——这两个类型没有任何继承或兼容关系,编译器肯定会报错。
正确的写法应该是把f1的类型声明为Future[Option[Int]]:
val f1: Future[Option[Int]] = Future{ None }
或者更简洁地让编译器自动推导类型(显式指定None的类型):
val f1 = Future{ None: Option[Int] }
错误2:map函数的分支返回类型不一致
再看f1.map里的match分支:
x match { case Some(i) => { 0 } // 这里返回的是Int类型 case None => { val f2 = Future{ 2 } f2.map(x => 1) // 这里返回的是Future[Int]类型 } }
map方法要求传入的函数所有分支必须返回相同类型,但你这里一个分支返回Int,另一个返回Future[Int],类型完全不统一,这是第二个编译失败的原因。
另外,你的方法最终要返回Future[Int],处理None时你返回了嵌套的Future[Int],这时候需要用flatMap而非map来展平嵌套的Future。修改后的代码如下:
def fut: Future[Int] = { val f1: Future[Option[Int]] = Future{ None } f1.flatMap(x => { println(x) x match { case Some(i) => Future.successful(0) // 把Int包装成Future[Int],和另一分支类型统一 case None => { val f2 = Future{ 2 } f2.map(_ => 1) } } }) }
简单解释下修改点:
- 用
flatMap替代map:因为我们的函数返回Future[Int],flatMap会把Future[Future[Int]]展平成Future[Int],符合方法的返回类型要求 - 在
Some(i)分支用Future.successful(0):把Int转换成Future[Int],保证两个分支的返回类型一致
这样修改后代码就能正常编译了。
内容的提问来源于stack exchange,提问作者Manu Chadha

