使用 Option 而不是 Null
在 Java(和其他语言)中,使用 null
是表示没有附加到引用变量的值的常用方法。在 Scala 中,使用 Option
比使用 null
更受欢迎。Option
包含可能是 null
的值。
None
是包含空引用的 Option
的子类。Some
是包含非空引用的 Option
的子类。
包装参考很容易:
val nothing = Option(null) // None
val something = Option("Aren't options cool?") // Some("Aren't options cool?")
这是调用可能返回 null 引用的 Java 库时的典型代码:
val resource = Option(JavaLib.getResource())
// if null, then resource = None
// else resource = Some(resource)
如果 getResource()
返回 null
值,则 resource
将成为 None
对象。否则它将是一个 Some(resource)
对象。处理 Option
的首选方法是使用 Option
类型中的高阶函数。例如,如果你想检查你的值是不是 None
(类似于检查 value == null
),你会使用 isDefined
函数:
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isDefined) { // resource is `Some(_)` type
val r: Resource = resource.get
r.connect()
}
同样,要检查 null
参考,你可以这样做:
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isEmpty) { // resource is `None` type.
System.out.println("Resource is empty! Cannot connect.")
}
你最好将 Option
视为 monad 并使用 foreach
处理 Option
的包装值(不使用’特殊’Option.get
方法)的条件执行:
val resource: Option[Resource] = Option(JavaLib.getResource())
resource foreach (r => r.connect())
// if r is defined, then r.connect() is run
// if r is empty, then it does nothing
如果需要 Resource
实例(与 Option[Resource]
实例相比),你仍然可以使用 Option
来防止空值。这里 getOrElse
方法提供了一个默认值:
lazy val defaultResource = new Resource()
val resource: Resource = Option(JavaLib.getResource()).getOrElse(defaultResource)
Java 代码不会轻易处理 Scala 的 Option
,因此在将值传递给 Java 代码时,打开 Option
,传递 null
或合理的默认值是一种很好的形式:
val resource: Option[Resource] = ???
JavaLib.sendResource(resource.orNull)
JavaLib.sendResource(resource.getOrElse(defaultResource)) //