Scala中使用Option包裹getOrNull结果报错的原因与解决办法
这个错误其实很好排查,咱们先搞清楚为什么会出现Option.type does not take parameters:
核心原因
最常见的情况是你用错了Option类——大概率是导入了Java的java.util.Option,而不是Scala标准库的scala.Option。
Java的Option是个接口,没有伴生对象的apply方法,没法直接用Option(xxx)这种方式创建实例;而Scala的scala.Option伴生对象提供了apply方法,支持Option(value)生成Some(value)或者None,这才是咱们想要的用法。
另外还有一种小概率情况:你的代码里自定义了一个叫Option的类/变量,和Scala标准库的重名了,导致编译器找不到正确的伴生对象。
解决步骤
1. 确保用的是Scala的Option
先检查代码顶部的导入,如果有import java.util.Option,删掉它,换成Scala的:
import scala.Option
或者直接用全限定名调用,避免混淆:
val r = scala.Option(getOrNull(someString.split("/")(0)))
2. 换个更Scala的写法(推荐)
其实你写的getOrNull完全没必要自己实现,Scala自带的Try就能完美解决这个需求,还更安全:
import scala.util.Try // 直接用Try包裹可能出错的代码,转成Option val r = Try(someString.split("/")(0)).toOption
Try会捕获所有非致命异常(包括数组越界、空指针这些),成功就返回Some(第一个元素),失败就返回None,比你只捕获NPE的getOrNull靠谱多了。
3. 如果你非要用自己的getOrNull
那得先修复它的局限性:你的函数只抓NullPointerException,但someString.split("/")(0)如果数组为空,抛的是ArrayIndexOutOfBoundsException,根本不会被捕获,还是会报错。可以改成捕获更多异常:
def getOrNull[T >: Null](f: => T): T = { try { f } catch { // 捕获数组越界和空指针,或者直接抓所有Exception case _: NullPointerException | _: ArrayIndexOutOfBoundsException => null } }
然后再用Scala的Option包裹调用结果就没问题了。
内容的提问来源于stack exchange,提问作者Clovis

