1. 程式人生 > >scala中的option[T]、Any、Nothing、Null、null、Nil、None、Some和Unit

scala中的option[T]、Any、Nothing、Null、null、Nil、None、Some和Unit

scala中的option[T]、Any、Nothing、Null、null、Nil、None和Unit

 

1 Option[T] 、 None 和 Some

Option定義:

package scala
@scala.SerialVersionUID(value = -114498752079829388)
sealed abstract class Option[+A]() extends scala.AnyRef with scala.Product with scala.Serializable {
  ...
}
object Option extends scala.AnyRef with scala.Serializable {
  implicit def option2Iterable[A](xo : scala.Option[A]) : scala.Iterable[A] = { /* compiled code */ }
  def apply[A](x : A) : scala.Option[A] = { /* compiled code */ }
  def empty[A] : scala.Option[A] = { /* compiled code */ }
}

Option[T]主要是用來避免NullPointerException異常的(Option本身是一個容器)


object Test {
  def main(args: Array[String]): Unit = {
    val option1: Option[Int] = Some(2018)
    val option2: Option[Int] = None

    val v1 = option1.getOrElse(0)
    println(v1)//輸出:2018
    val v2 = option2.getOrElse(0)
    println(v2)//輸出: 0

    //我們明確知道option1是有值的
    val v3 = option1.get
    println(v3)//輸出:2018

    val map:Map[Int,String] = Map(1 -> "aaa", 2 -> "bbbb", 3 -> "cccc")
    //根據key獲取map中的值,map中的value都是一個Option
    val v4:Option[String] = map.get(1)
    println(v4)//輸出:Some(aaa)
    //根據key獲取map中的值,並求出值的長度
    println(map.get(1).getOrElse("").length())//輸出:3
    println(map.get(10).getOrElse("").length())//輸出:0
    println(map.get(10))//輸出:None
    //檢測Option容器中的元素是否為 None
    println(map.get(1).isEmpty)//輸出:false
    println(map.get(10).isEmpty)//輸出:true
    
  }
}

Option定義了getOrElse方法,在獲取容器中的值是如果有返回容器中的值,如果沒有就返回給定的值,這一點和Java8的一樣。

Option定義了get方法,直接獲取容器中的元素,該操作不安全,可能會遇到None,None呼叫get就會出現空指標異常

Option定義了isEmpty方法,可以判斷容器中是不是None

Option的apply()方法可以返回None/Some可知None或Some必定是Option的子類,None與Some原始碼

None 原始碼

package scala
@scala.SerialVersionUID(value = 5066590221178148012)
case object None extends scala.Option[scala.Nothing] with scala.Product with scala.Serializable {
  def isEmpty : scala.Boolean = { /* compiled code */ }
  def get : scala.Nothing = { /* compiled code */ }
}



Some原始碼
package scala
@scala.SerialVersionUID(value = 1234815782226070388)
final case class Some[+A](val value : A) extends scala.Option[A] with scala.Product with scala.Serializable {
  def isEmpty : scala.Boolean = { /* compiled code */ }
  def get : A = { /* compiled code */ }
  @scala.deprecated("Use .value instead.", "2.12.0")
  def x : A = { /* compiled code */ }
}

 

Option的常用方法:

序號 方法及描述
1

def get: A

獲取可選值

2

def isEmpty: Boolean

檢測可選型別值是否為 None,是的話返回 true,否則返回 false

3

def productArity: Int

返回元素個數, A(x_1, ..., x_k), 返回 k

4

def productElement(n: Int): Any

獲取指定的可選項,以 0 為起始。即 A(x_1, ..., x_k), 返回 x_(n+1) , 0 < n < k.

5

def exists(p: (A) => Boolean): Boolean

如果可選項中指定條件的元素存在且不為 None 返回 true,否則返回 false。

6

def filter(p: (A) => Boolean): Option[A]

如果選項包含有值,而且傳遞給 filter 的條件函式返回 true, filter 會返回 Some 例項。 否則,返回值為 None 。

7

def filterNot(p: (A) => Boolean): Option[A]

如果選項包含有值,而且傳遞給 filter 的條件函式返回 false, filter 會返回 Some 例項。 否則,返回值為 None 。

8

def flatMap[B](f: (A) => Option[B]): Option[B]

如果選項包含有值,則傳遞給函式 f 處理後返回,否則返回 None

9

def foreach[U](f: (A) => U): Unit

如果選項包含有值,則將每個值傳遞給函式 f, 否則不處理。

10

def getOrElse[B >: A](default: => B): B

如果選項包含有值,返回選項值,否則返回設定的預設值。

11

def isDefined: Boolean

如果可選值是 Some 的例項返回 true,否則返回 false。

12

def iterator: Iterator[A]

如果選項包含有值,迭代出可選值。如果可選值為空則返回空迭代器。

13

def map[B](f: (A) => B): Option[B]

如果選項包含有值, 返回由函式 f 處理後的 Some,否則返回 None

14

def orElse[B >: A](alternative: => Option[B]): Option[B]

如果一個 Option 是 None , orElse 方法會返回傳名引數的值,否則,就直接返回這個 Option。

15

def orNull

如果選項包含有值返回選項值,否則返回 null。

2 Any

Any是abstract類,它是Scala類繼承結構中最底層的。所有執行環境中的Scala類都是直接或間接繼承自Any這個類,它就是其它語言(.Net,Java等)中的Object。

Any 處於型別結構樹的根部位置,Any 沒有父類,但有三個子類:

 AnyVal, 價值型別和價值類的父類。
 AnyRef,所有引用型別的父類。
•通用特徵(universal trait)。

AnyVal 有九個具體子類,稱為值型別。其中七個是數字值型別:Byte、Char、Short、Int、Long、Float 和Double。餘下的兩個是非數字值型別,Unit 和Boolean。

除AnyVal及其子類外,其他型別均為引用型別。它們派生自AnyRef,AnyRef 是java.lang.Object的別名。在Java 的物件模型中,Object 並沒有一個封裝了原生型別和引用型別的父類,因為Java 對原生型別做了特殊處理。

3.Nothing

Nothing是所有其他型別的子類

Nothing 在Java 中沒有類似的概念,但它填補了存在於Java 型別系統中的空白。Nothing 在編譯器裡的實現相當於以下宣告:

package scala
abstract final class Nothing extends Any

Nothing 實際上繼承了Any。根據型別系統裡的構造規則,Nothing 是所有其他型別的子類,無論是引用型別還是值型別。換句話說,Nothing 繼承了所有一切(everything),這讓它的名字聽起來很奇怪。

Nothing 沒有例項,Nothing 為型別系統提供了兩種功能:

1、用來當做Nil的型別List[Nothing]

package scala.collection.immutable
object Nil extends List[Nothing] with Product with Serializable

 Nil表示一個空的list,與list中的元素型別無關,他可以同時表示List[任意型別]的空集合。

2、Nothing 用來表示終止程式,非正常型別的返回值型別

我們可以臨時呼叫??? 方法來定義其他的方法,使得方法定義完整,並通過編譯。但如果呼叫該方法,就會丟擲異常。以下是??? 的定義:

package scala
object Predef {
...
def ??? : Nothing = throw new NotImplementedError
...
}

4.Null與null

Null 對於大多數語言而言是個熟悉的概念。儘管這些語言通常並沒有定義Null 型別,僅僅定義了關鍵字null,用於向引用變數賦值,表示該變數實際上沒有值。Null 在編譯器裡的實現相當於以下宣告:

package scala
abstract final class Null extends AnyRef

該宣告不允許子類派生以及建立例項,但執行時環境提供了一個例項,就是我們最熟悉的、最喜愛、最可惡的null,我們在建立例項時僅僅是想宣告一下變數,暫時不建立例項,這是很容易想到null物件,有了它我們就可以順利編寫程式了,所以null是我們最熟悉、最喜愛的例項,所謂樂極生悲,愛極必反,null也不例外,他也是空指標的萬惡之源,所以他也是最可惡的例項。

Null 被明確定義為AnyRef 的一個子型別,但它也是所有AnyRef 型別的子型別。這是型別系統允許你用null 給任何引用型別賦值的正常做法。另一方面,因為null 不是AnyVal 的子型別,所以不可以用null 給Int 賦值。於是,Scala 的null 與Java 的null 完全相同,因為它必須與Java 的null 共存於JVM。否則,Scala 會破壞null 的概念,引起很多潛在的bug。

5、Nil

Nil是Scala宣告一個空列表的專用型別,它是繼承了List[Nothing] 的物件,它只需要一個例項,因為它沒有攜帶任何“狀態”(元素)。由於List 的型別引數是協變的,對於任意型別A,Nil 是所有List[A] 的子型別。所以,我們不需要分開Nil[A] 例項,一個例項就夠了。

6、Unit

先不多說,原始碼在此

package scala
final abstract class Unit() extends scala.AnyVal {
  override def getClass() : _root_.scala.Predef.Class[scala.Unit] = { /* compiled code */ }
}
object Unit extends scala.AnyRef with scala.AnyValCompanion {
  def box(x : scala.Unit) : scala.runtime.BoxedUnit = { /* compiled code */ }
  def unbox(x : java.lang.Object) : scala.Unit = { /* compiled code */ }
  override def toString() : java.lang.String = { /* compiled code */ }
}

Unit是函式和方法的返回值型別,表示沒有返回值。這一點和java的void有點像,但不等同於java的void,因為java的void可以返回null。