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