【Scala】使用Option、Some、None,避免使用null
避免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.get
at scala.None$.get(Option.scala:347)
at scala.None$.get(Option.scala:345)
... 33 elided
scala> capitals get "France" get
warning: there was one feature warning; re-run with -feature for details
res3: String = Paris
scala> (capitals get "North Pole") getOrElse "Oops"
res7: String = Oops
scala> capitals get "France" getOrElse "Oops"
res8: String = Paris
通过模式匹配分离可选值,假设匹配的值是Some的话,将Some里的值抽出赋给x变量:
def showCapital(x: Option[String]) = x match {
case Some(s) => s
case None => "?
"
}
提示
Scala程序使用Option非常频繁,在Java中使用null来表示空值,代码中非常多地方都要加入null关键字检測,不然非常easy出现NullPointException。
因此Java程序须要关心那些变量可能是null,而这些变量出现null的可能性非常低,但一但出现,非常难查出为什么出现NullPointerException。
Scala的Option类型能够避免这样的情况,因此Scala应用推荐使用Option类型来代表一些可选值。使用Option类型,读者一眼就能够看出这样的类型的值可能为None。
实际上,多亏Scala的静态类型,你并不能错误地尝试在一个可能为null的值上调用方法。
尽管在Java中这是个非常easy犯的错误,它在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] = None
scala> def printContentLength(x: Option[String]) {
| for (c <- x){
| println(c.length)
| }
| }
printContentLength: (x: Option[String])Unit
scala> printContentLength(value1)
6
scala> printContentLength(value2)
map操作
在函数式编程中有一个核心的概念之中的一个是转换。所以大部份支持函数式编程语言,都支持一种叫map()的动作。这个动作是能够帮你把某个容器的内容,套上一些动作之后,变成还有一个新的容器。
如今我们考虑怎样用Option的map方法实现length: xxx的输出形式:
先算出 Option 容器内字符串的长度
然后在长度前面加上 “length: ” 字样
最后把容器走訪一次,印出容器内的东西
scala> value1.map(_.length).map("length: " + _).foreach(println)
length: 6
scala> value1.map("length: " + _.length).foreach(println)
length: 6
透过这样「转换」的方法,我们一样能够达成想要的效果。并且相同不用去做「是否为 None」的推断。
转载请注明作者Jason Ding及其出处
GitCafe博客主页(http://jasonding1354.gitcafe.io/)
Github博客主页(http://jasonding1354.github.io/)
CSDN博客(http://blog.csdn.net/jasonding1354)
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
Google搜索jasonding1354进入我的博客主页
【Scala】使用Option、Some、None,避免使用null的更多相关文章
- Scala的Option类型
Scala的Option类型 为了让所有东西都是对象的目标更加一致,也为了遵循函数式编程的习惯,Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型.在没有值的时候,使用No ...
- scala中option、None、some对象
转载:http://www.jianshu.com/p/95896d06a94d 1.option类型避免对象是空值,造成空指针异常. 2.None对象表示null,在没有对象返回时使用,some在有 ...
- scala的Option
当一个函数既要返回对象,又要返回null的时候,使用Option[] http://www.runoob.com/scala/scala-options.html Option是scala的选项,用来 ...
- 【scala】Option类型
一般来说,对于每种语言都会有一个关键字来表示一个对象引用的“无”.在Java中使用的是null. 而Scala则融合了函数式编程的风格,当预计到变量或者函数返回值可能不会引用任何值的时候,使用Opti ...
- scala中Option和Some
Option的解释: Represents optional values. Instances of Option are either an instance of scala.Some or t ...
- Scala之Option: Some None
Option类型本身没有实现,而是依赖两个子类型提供具体实习那:Some和None.Some是iyge类型参数化的单元素集合,None是一个空集合. ----<scala学习手册>P119
- Desugar Scala(17) -- Option和for,以及脑子里发生的事情
欢迎关注我的新博客地址:http://cuipengfei.me/blog/2014/08/30/options-for/ Scala里的forkeyword是个非常有趣的东西. 能够用来把多层嵌套f ...
- Spark记录-scala快速入门
1.hello world程序 object HelloWorld { def main(args: Array[String]) { println("Hello,World!" ...
- Scala模式匹配常用
今天在工作中遇到的几个小问题,总结一下: 1.因为业务需要调用PHP的接口,获取到的返回体需要做一段逻辑处理,然而某个字段接收到的参数是io.serializable类型,字段的类型不是预期的stri ...
- 转载:【Scala】使用Option、Some、None,避免使用null
转载自Jason DingGitCafe博客主页(http://jasonding1354.gitcafe.io/)Github博客主页(http://jasonding1354.github.io/ ...
随机推荐
- oracle to_char FM099999
to_char(column,'FM099999') The FM in the format removes leading and trailing blanks.
- POJ 1912 A highway and the seven dwarfs (凸包)
[题目链接] http://poj.org/problem?id=1912 [题目大意] 给出一些点,表示一些屋子,这些屋子共同组成了村庄,现在要建一些高速公路 问是否经过了村庄. [题解] 这些屋子 ...
- 【基数排序】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) C. Jon Snow and his Favourite Number
发现值域很小,而且怎么异或都不会超过1023……然后可以使用类似基数排序的思想,每次扫一遍就行了. 复杂度O(k*1024). #include<cstdio> #include<c ...
- 【bzoj1486】【[HNOI2009]梦幻布丁】启发式链表合并(详解)
(画师当然是武内崇啦) Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3 ...
- 【莫比乌斯反演+分块】BZOJ1101-[POI2007]Zap
[题目大意] 对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d. [思路] 前面的思路同HDU1695 不过不同的是这道题中(a,b)和(b ...
- python3开发进阶-Django框架的详解
一.MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分: 模型(Model).视图(View)和控制器(Con ...
- 五角数 Exercise06_01
/** * @author 冰樱梦 * 题目:五角数 * 时间:2018年下半年 * * */ public class Exercise06_01 { public static void main ...
- linux下目录大小为什么是4K?一个目录下最多有个多少个子目录?最多有多少个文件?ls -l显示的内容中total到底是什么?
子目录数太多,会影响搜索性能. 在同一个路径下,一级子目录的个数限制为31998,如果你的应用生成的目录可能会超过这个数,那要注意进行目录分级.例如,如果目录名为数字的话,可以将数字除以10000后的 ...
- Heartbleed漏洞利用程序
#!/usr/bin/python # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspe ...
- Linux内核分析(三)内核启动过程分析——构造一个简单的Linux系统
一.系统的启动(各历史节点) 在最开始的时候,计算机的启动实际上依靠一段二进制码,可以这么理解,他并不是一个真正的计算机启动一道程序.计算机在开始加电的时候几乎是没有任何用处的,因为RAM芯片中包括的 ...