我正在使用scala,并且最近继承了一些需要移植的Java代码,不幸的是在Scala中重写它并不在卡片中。它有一个深层嵌套的对象结构,任何级别都可以为null。我常常只关心嵌套中的深层价值。
理想情况下,我会这样做:
Option(foo.blah.blarg.doh)
但如果foo.blah.blarg中的任何一个为null,则会产生一个NPE。
现在我已经把它包装在Try:
中了Try(Option(foo.blah.blarg.doh)).getOrElse(None)
请注意,使用.toOption并不能正常工作,因为如果链的最后一位为空,它可能会导致Some(null)。
我不是特别喜欢这种结构,还有其他任何想法吗?
答案 0 :(得分:5)
flatMap it:
for {
a <- Option(foo)
b <- Option(a.blah)
c <- Option(b.blarg)
d <- Option(c.doh)
} yield d
答案 1 :(得分:3)
利用by-name参数构建自己的构造:
def handleNull[T](x: => T): Option[T] = try Option(x) catch {
case _: NullPointerException => None
}
handleNull(foo.blah.blarg.doh)
答案 2 :(得分:2)
您还可以使用此方法安全地浏览一系列调用,其中每个步骤都可以返回null。它比Option和flatMaps更方便使用。
/**
* @param expr expression which is a chain of java calls
* @tparam A the type of the last expression
* @return Some(A) if there was no null, None otherwise
*/
def safeTraverseNullableChain[A](expr: => A): Option[A] = {
Try(expr).filter(_ != null).toOption
}
答案 3 :(得分:2)
如果您的项目中有cats
库,则可以使用其扩展方法:
import cats.implicits._
Either
.catchOnly[NullPointerException](foo.blah.blarg.doh)
.collectFirstSome(Option(_))