使用 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)) //