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

后来依然我行我素在Scala里使用null, 结果就是经常被NullPointerException折磨得阴魂不散...于是终于领悟.

WHY?

举个例子:

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

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

  

然后有这么一个map

val map1 = Map(1 -> A(111, 1111), 2 -> A(222, 2222), 3 -> A(333, 3333))

  

然后有这么一段业务逻辑需要从这个map中取出其中2个A,并且拿他们的a属性相加

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

不仅这样, 你在报错输出中得到的抛出异常的代码就是上面第3行println这句, 单从日志来看你根本无法知道别人给你有问题的是key1还是key2

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

可是一旦真的是null, 只能庆幸这个报错不是出现在生产环境中了.

HOW?

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

很简单, scala提供的Option,和None就是个非常好的设计! 有多好? 代码撸起

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

    val list = List(1 ,2, 3, 4)[Int]
val found : Option[Int] = list.find(_ > 5)
found match {
case None => //由你决定找不到怎么办
case Some(value) =>//由你决定找到想要的value值怎么办
}

  

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

    //可以先用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

当然更优雅的写法就像上面那样, 使用匹配模式, 在出现多种情况之间选择做什么事情.

Option还提供了其他很骚的用法. 你甚至可以把Option当成是一个只能容纳1个元素的容器来看待.

假设又有那么一个需求, 我有一个Option[A], 我不确定这个Option是否==None, 但我想要尝试取出里面的A对象的a属性, 如果没有的话就给我个0吧, 那么代码可以这么写

    val aOpt : Option[A] = //我不确定他是None, 还是Some(A)反正别人给我的

    //就这么简单粗暴
val myVal1 :Int = if(aOpt.isEmpty) 0 else aOpt.get.a //也可以先把Option[A]map成Option[Int](这里是Int,因为是A的a属性的类型), 再使用getOrElse 取不到就给个自己定的默认值
val myVal2 :Int = aOpt.map(aObj => aObj.a).getOrElse(0)

  

还有另一个需求, 我想知道这个Option[A] 里的A对象的a属性是否等于100

val has100 :Boolean = aOpt.exists(aObj => aObj.a == 100)

  

Final

已经有不少文章吐槽null的设计是多么糟糕: 传送门请看:http://www.php230.com/weixin1446428231.html

既然scala已经考虑到并提供优雅代码的解决方式. 那以后可以少在scala里给用null了.

Scala不使用null 而使用Option,None,Some的好处的更多相关文章

  1. Scala中的"null" 和“_”来初始化对象

    Alternatives Use null as a last resort. As already mentioned, Option replaces most usages of null. I ...

  2. Scala 学习笔记之集合(7) Option

    object CollectionDemo8 { def main(args: Array[String]): Unit = { //Option集合的使用,可以用来安全的判断null或非null,放 ...

  3. 转载:【Scala】使用Option、Some、None,避免使用null

    转载自Jason DingGitCafe博客主页(http://jasonding1354.gitcafe.io/)Github博客主页(http://jasonding1354.github.io/ ...

  4. 【Scala】使用Option、Some、None,避免使用null

    避免null使用 大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是"无",在Java,它是null.在Java 里,null 是一个关键字,不是一个对象,所以对它调用不 ...

  5. scala Option 里的 orNull orElse getOrElse 区别和使用

    Scala Option Scala Option类型用来表示一个值是可选的(有值或无值) Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some ...

  6. scala(一)Nothing、Null、Unit、None 、null 、Nil理解

    相对于java的类型系统,scala无疑要复杂的多!也正是这复杂多变的类型系统才让OOP和FP完美的融合在了一起! Nothing: 如果直接在scala-library中搜索Nothing的话是找不 ...

  7. Scala Option类型

    转载自: Scala 初学者指南, 这里有一系列很棒的文章 类型 Option 可能你已经见过它在 Map API 中的使用:在实现自己的提取器时,我们也用过它, 然而,它还需要更多的解释. 你可能会 ...

  8. scala中option、None、some对象

    转载:http://www.jianshu.com/p/95896d06a94d 1.option类型避免对象是空值,造成空指针异常. 2.None对象表示null,在没有对象返回时使用,some在有 ...

  9. Scala 技术笔记之 Option Some None

    避免null使用 大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是“无”,在Java,它是null.在Java 里,null 是一个关键字,不是一个对象,所以对它调用任何方法都是非法的.但 ...

随机推荐

  1. Python知识点入门笔记——特色数据类型(字典)

    Python中字典是一些列键 (key) 值 (value) 对组成的,形式如下 {键1:值1,键2:值:2} 每个键值对用冒号隔开,每对之间用逗号隔开 键必须是唯一的,必须是不可变的,如字符串,数字 ...

  2. Python9-IO模型-day41

    # 进程:启动多个进程,进程之间是由操作系统负责调用# 线程:启动多个线程,真正由被cpu执行的最小单位实际是线程# 开启一个线程,创建一个线程,寄存器.堆栈# 关闭一个线程# 协程# 本质上是一个线 ...

  3. dijkstra与他的优化!!!

    目录 SPFA已死,有事烧纸 Dijkstra 配对堆 引言 讲解 合并 修改 弹出堆顶pop 代码 结合! 1 2 @ SPFA已死,有事烧纸 其实我本人也是一个SPFA的忠诚用户,至少我的最少费用 ...

  4. 并查集:HDU5326-Work(并查集比较简单灵活的运用)

    Work HDU原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5326 Time Limit: 2000/1000 MS (Java/Others) M ...

  5. 数论:HDU1066-Last non-zero Digit in N!

    题目: Last non-zero Digit in N! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  6. readhat7.0 bond配置

    Bonding的模式一共有7种: 1.mode=0(balance-rr)(平衡抡循环策略) 概念:链路负载均衡,增加带宽,支持容错,一条链路故障会自动切换正常链路.交换机需要配置聚合口,思科叫por ...

  7. 2190: [SDOI2008]仪仗队(欧拉函数)

    2190: [SDOI2008]仪仗队 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 3235  Solved: 2089 Description 作 ...

  8. Go语言之反射(三)

    结构体转JSON JSON格式是一种用途广泛的对象文本格式.在Go语言中,结构体可以通过系统提供的json.Marshal()函数进行序列化.为了演示怎么样通过反射获取结构体成员以及各种值的过程,下面 ...

  9. Asp.net自定义控件开发任我行(3)-Render

    摘要 上一篇我们讲到了自定义标签TagPrefix用法,此篇我们来讲一下控件的呈现,主要是呈现下拉框 内容 呈现的方法有,Render,RenderControl,RenderChildren,这三个 ...

  10. IOS开发---菜鸟学习之路--(七)-自定义UITableViewCell

    本篇将介绍如何自定义 UITableViewCell 首先选择新建文件 可以直接使用快捷键 COMMAND+n打开新建页面,然后选Objective-C class 然后选择继承之UITableVie ...