避免null使用

大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是“无”,在Java,它是null。在Java 里,null 是一个关键字,不是一个对象,所以对它调用任何方法都是非法的。但是这对语言设计者来说是一件令人疑惑的选择。为什么要在程序员希望返回一个对象的时候返回一个关键字呢?

Scala的Option类型

为了让所有东西都是对象的目标更加一致,也为了遵循函数式编程的习惯,Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型。在没有值的时候,使用None,这是Option的一个子类。如果有值可以引用,就使用Some来包含这个值。Some也是Option的子类。
None被声明为一个对象,而不是一个类,因为我们只需要它的一个实例。这样,它多少有点像null关键字,但它却是一个实实在在的,有方法的对象。

应用例子

Option类型的值通常作为Scala集合类型(List,Map等)操作的返回类型。比如Map的get方法:

scala> val capitals = Map("France"->"Paris", "Japan"->"Tokyo", "China"->"Beijing")
capitals: scala.collection.immutable.Map[String,String] = Map(France -> Paris, Japan -> Tokyo, China -> Beijing)scala> capitals get "France"
res0: Option[String] = Some(Paris)scala> capitals get "North Pole"
res1: Option[String] = None

Option有两个子类别,Some和None。当程序回传Some的时候,代表这个函式成功地给了你一个String,而你可以透过get()函数拿到那个String,如果程序返回的是None,则代表没有字符串可以给你。
在返回None,也就是没有String给你的时候,如果你还硬要调用get()来取得 String 的话,Scala一样是会抛出一个NoSuchElementException异常给你的。
我们也可以选用另外一个方法,getOrElse。这个方法在这个Option是Some的实例时返回对应的值,而在是None的实例时返回传入的参数。换句话说,传入getOrElse的参数实际上是默认返回值。

scala> capitals get "North Pole" get
warning: there was one feature warning; re-run with -feature for details
java.util.NoSuchElementException: None.getat scala.None$.get(Option.scala:347)at scala.None$.get(Option.scala:345)... 33 elidedscala> capitals get "France" get
warning: there was one feature warning; re-run with -feature for details
res3: String = Parisscala> (capitals get "North Pole") getOrElse "Oops"
res7: String = Oopsscala> capitals get "France" getOrElse "Oops"
res8: String = Paris

通过模式匹配分离可选值,如果匹配的值是Some的话,将Some里的值抽出赋给x变量:

def showCapital(x: Option[String]) = x match {case Some(s) => scase None => "?"
}

提示

Scala程序使用Option非常频繁,在Java中使用null来表示空值,代码中很多地方都要添加null关键字检测,不然很容易出现NullPointException。因此Java程序需要关心那些变量可能是null,而这些变量出现null的可能性很低,但一但出现,很难查出为什么出现NullPointerException。
Scala的Option类型可以避免这种情况,因此Scala应用推荐使用Option类型来代表一些可选值。使用Option类型,读者一眼就可以看出这种类型的值可能为None。

实际上,多亏Scala的静态类型,你并不能错误地尝试在一个可能为null的值上调用方法。虽然在Java中这是个很容易犯的错误,它在Scala却通不过编译,这是因为Java中没有检查变量是否为null的编程作为变成Scala中的类型错误(不能将Option[String]当做String来使用)。所以,Option的使用极强地鼓励了更加弹性的编程习惯。

详解Option[T]

在Scala里Option[T]实际上是一个容器,就像数组或是List一样,你可以把他看成是一个可能有零到一个元素的List。
当你的Option里面有东西的时候,这个List的长度是1(也就是 Some),而当你的Option里没有东西的时候,它的长度是0(也就是 None)。

for循环

如果我们把Option当成一般的List来用,并且用一个for循环来走访这个Option的时候,如果Option是None,那这个for循环里的程序代码自然不会执行,于是我们就达到了「不用检查Option是否为None这件事。

scala> val map1 = Map("key1" -> "value1")
map1: scala.collection.immutable.Map[String,String] = Map(key1 -> value1)scala> val value1 = map1.get("key1")
value1: Option[String] = Some(value1)scala> val value2 = map1.get("key2")
value2: Option[String] = Nonescala> def printContentLength(x: Option[String]) {|   for (c <- x){|     println(c.length)|   }| }
printContentLength: (x: Option[String])Unitscala> printContentLength(value1)
6scala> printContentLength(value2)

map操作

在函数式编程中有一个核心的概念之一是转换,所以大部份支持函数式编程语言,都支持一种叫map()的动作,这个动作是可以帮你把某个容器的内容,套上一些动作之后,变成另一个新的容器。
现在我们考虑如何用Option的map方法实现length: xxx的输出形式:

先算出 Option 容器内字符串的长度
然后在长度前面加上 "length: " 字样
最后把容器走访一次,印出容器内的东西

scala> value1.map(_.length).map("length: " + _).foreach(println)
length: 6scala> value1.map("length: " + _.length).foreach(println)
length: 6

透过这样「转换」的方法,我们一样可以达成想要的效果,而且同样不用去做「是否为 None」的判断。

scala中使用Option、Some、None,避免使用null相关推荐

  1. Scala系列-4、scala中特质、柯里化、闭包等

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 传送门:大数据系列文章目录 目录 scala中特质 特质作为接口使用 特质中放置非抽象的成员 ...

  2. scala中NULL的option定义的字段初始化用Some

    例子: var in = None:Option[FileInputStream] var out = None:Option[FileOutputStream] try{in = Some(new ...

  3. (转)Scala中的Some和Option

    原文链接 Scala Option[T] is a container for zero or one element of a given type. An Option[T] can be eit ...

  4. scala中何时使用下划线_在Scala中使用下划线

    scala中何时使用下划线 Underscore (_) character is reserved in Scala and has multiple usages in the programmi ...

  5. Scala中的None,Nothing,Null,Nil

    在scala中这四个类型名称很类似,作用确实完全不同的. None是一个object,是Option的子类型,定义如下 case object None extends Option[Nothing] ...

  6. Scala学习之Option类

    今天特意学习一下Option类型 一般来说,对于每种语言都会有一个关键字来表示一个对象引用的"无".比如在Java中使用的是null. 在Scala中是融合了函数式编程的风格,当预 ...

  7. Scala中如何优雅的处理Null

    前言 如果在scala代码还在使用id! = null,可能会被有的人嘲笑,都什么年代了,竟然还有这样的写法,NullPointerException见少了吧? 不过,据统计: Spark 源代码使用 ...

  8. 【Scala】Scala中的模式匹配、类型参数与隐式转换

    1.模式匹配 (1)概述 模式匹配是Scala中非常有特色,非常强大的一种功能.模式匹配,其实类似于Java中的swich case语法,即对一个值进行条件判断,然后针对不同的条件,进行不同的处理.但 ...

  9. scala中的match详解

    Scala中提供了比java,c更加强大的switch语句--match,而且不用担心因为忘记写break语句而发生case穿透 1.更好的switch 与if,类似match也是表达式,如下一个用于 ...

最新文章

  1. python 遍历文件夹和文件
  2. 快来看看Google出品的Protocol Buffer,别仅仅会用Json和XML了
  3. laravel5.8笔记六:公共函数和常量设置
  4. Gensim初步使用和详细解释(该代码只能处理英文,处理中文不可用该代码)
  5. php无法post,PHP无法获得post数据
  6. Android之发送短信后按钮(60秒)变灰色每隔一秒递减显示
  7. python如何输出两列数据_如何用python将一列数据分为两列?
  8. 计算机视觉图像去噪原理,图像去噪方法研究进展
  9. Security+ 学习笔记1 恶意软件
  10. php 远程文件是否存在,如何通过php判断本地及远程文件是否存在
  11. js函数、事件、补充知识
  12. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第3节 两种获取Stream流的方式_2_Stream流中的常用方法_forEach...
  13. 全网首发:编译Android doubango时,armv7-a编译不出来的解决办法
  14. 演绎、归纳与前言结构——Leo鉴书83
  15. 如何剪裁证件照大小?2寸证件照片怎么制作?
  16. diskgenius扩容c盘重启电脑卡住_DiskGenius怎么给C盘扩容?DiskGenius无损调整C盘容量方法 (全文)...
  17. 远程服务器 检索{00024500-0000-0000-C000-000000000046}组件失败 80080005 服务器运行失败 解决方案
  18. oppo系统工程师暑期实习生面经(已OC)
  19. 误发邮件如何能撤回?
  20. Win10+RTX3060配置CUDA等深度学习环境

热门文章

  1. 计算机基础知识预备知识,计算机预备知识详解.ppt
  2. python教学案例-Python机器学习经典实例
  3. java实现账号单一ip登录,使用Java实现简单后台访问并获取IP示例
  4. NoSQL之Redis非关系数据库(redis概述,持久化,RDB持久化,AOF持久,内存碎片)
  5. OpenStack 的部署T版(二)——Keystone组件
  6. Web服务-Nginx网页服务
  7. linux 无法访问docker mysql8_Apple M1芯片不支持Docker?Docker:正在努力适配
  8. TOMCAT部署项目的方式
  9. amd显卡风扇调节_非公版才是真爱 讯景XFX RX6800 XT海外版显卡评测
  10. seir模型的微分方程怎么写_抖音文案怎么写?6种热门文案写作模型