Bootstrap

Scala之Option、Some、None

Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型。在没有值的时候,使用None,这是一个对象。如果有值可以引用,就使用Some来包含这个值。Some也是Option的子类。

刚接触Scala时就很奇怪, 为什么Java已经有null了,却偏偏还要弄出个None

WHY?

举个例子:

假设有一个简单的对象A, A类里有2个Int属性, a和b

1

case class A(val a : Int, val b : Int)

  

然后有这么一个map

1

val map1 = Map(1 -> A(1111111), 2 -> A(2222222), 3 -> A(3333333))

  

然后有这么一段业务逻辑

1

2

3

val key1 :Int = //其他地方给我的值,我也不知道具体是多少

val key2 :Int = //其他地方给我的值,我也不知道具体是多少

println(map1.getOrElse(key1, null).a + map1.getOrElse(key2, null).a) //111 + 报 NullPointerException

  

那么恭喜你, 遇到了NullPointerException. 为什么? 假设别人给你的key1=1, key2=4, 那么map1.getOrElse(key2, null).a 将会报出NullPointerException

所以在Java中, 一个对象的引用, 已经被默认为可能会是null了, 但有时候敲代码时会极度容易犯错, 同时就会信心满满的认为 "这个对象怎么可能是null呢?",

 

HOW?

那么我们如何在scala里避免使用null?

很简单, scala提供的Option,和None就是个非常好的设计

像scala List里, 如果我要查找一个list里面符合要求的元素, 不一定能找得到, 所以返回的是一个Option[元素类型]

1

2

3

4

5

6

val list = List(1 ,234)[Int]

val found : Option[Int] = list.find(_ > 5)

found match {

  case None => //由你决定找不到怎么办

  case Some(value) =>//由你决定找到想要的value值怎么办

}

  

所以对于之前的需求,一段业务逻辑需要从这个map中取出其中2个A,并且拿他们的a属性相加

1

2

3

4

5

6

7

8

9

10

11

12

13

//可以先用get, get 出来的东西是个 Option[A], 再做判断

var finalResult = 0 //0默认值

(map1.get(key1), map2.get(key2)) match {

  case (Some(value1), Some(value2)) =>

    //都找到了, 可以愉快的相加了

    finalResult = value1.a + value2.a

  case (None, Some(value2)) =>

    //第一个找不到, 第二个找到了怎么办的代码

  case (Some(value1), None) =>

    //第一个找到了, 第二个找不到怎么办的代码

  case _=>

    //其他情况

}

  

scala的Map可以使用get方法获取对象, 获取出来的是一个 Option[对象类型], 为什么不像java那样直接取出null? 这里就是因为要考虑到取不出来东西的情况.

所以Option存在的意义, 就是为了在代码中注明, 让大家一看就知道: "这个东西可能是空的! 你们用的时候给我小心点" 这样的暗示.

有了这个暗示, 你可就不能随意取出option里面的东西了, 警醒你每次使用, 都要先判断. isEmpty 或是 nonEmpty

 

 

 

 

 

 

;