Scala的有即Any,Scala的无是Null,null,Nil,Nothing,None,Unit.那么这几种空有什么区别呢?

一、Null&null

很多人一辈子都没有走出这个无。Null是一个Trait,你不能创建她它的实例。但是Scala在语言层面上存在一个Null的实例,那就是null。Java中的null意味着引用并没有指向任何对象。但存在一个悖论,一切都是对象,那没有对象是不是也是对象呢?Scala定义了一个类似于对象语义的Null,和一个值语义的null。这样面向对象在空引用的情况下完备了。如果你写了一个带有Null作为参数的对象,那么你传入的参数只能是null,或者指向Null的引用。

scala> def tryit(thing: Null): Unit = { println("That worked!"); }
tryit: (Null)Unit scala> tryit("hey")
<console>:6: error: type mismatch;
found : java.lang.String("hey")
required: Null
tryit("hey")
^ scala> val someRef: String = null
someRef: String = null scala> tryit(someRef)
<console>:7: error: type mismatch;
found : String
required: Null
tryit(someRef)
^ scala> tryit(null)
That worked! scala> val nullRef: Null = null
nullRef: Null = null scala> tryit(nullRef)
That worked!

第四行我们试图传入一个String,自然不能工作。第14行我们传入一个null引用,但是任然不能工作,为什么呢?因为null引用指向的是String类型。它可能在运行时是null,但是在编译时类型检查却不认同,编译器认为他是个String

二、Nil

Nil是一个继承List[Nothing]的对象,我们随后讨论Nothing。它就是一个空的列表,下面是一些使用实例:

scala> Nil
res4: Nil.type = List() scala> Nil.length
res5: Int = 0 scala> Nil + "ABC"
res6: List[java.lang.String] = List(ABC) scala> Nil + Nil
res7: List[object Nil] = List(List())

可以看出,Nil就是一个可以封装任何东西的空容器。它的长度为0。它并不是一无所有,它是一个容器,一个列表,只是没有存放内容而已。

三、Nothing

Nothing可能比较难理解。Nothing也是一个Trait,它继承自Any,而Any是整个Scala类型系统的根。Nothing是没有实例的,但它时任何对象的子类,他是List的子类,是String的子类,是Int的子类,是任何用户自定义类型的子类。

前面提到Nil是一个空的List[Nothing]。由于Nothing是任何类型的子类,那么Nil就可以当做是一个空的String List,空的Int List,甚至使Any List。Nothing比较适合用来定义基类容器。

scala> val emptyStringList: List[String] = List[Nothing]()
emptyStringList: List[String] = List() scala> val emptyIntList: List[Int] = List[Nothing]()
emptyIntList: List[Int] = List() scala> val emptyStringList: List[String] = List[Nothing]("abc")
<console>:4: error: type mismatch;
found : java.lang.String("abc")
required: Nothing
val emptyStringList: List[String] = List[Nothing]("abc")

第一行,我们将一个List[Nothing]赋值给一个List[String]。一个Nothing是一个String,因此是正确的。第四行,我们将一个List[Nothing]赋值给一个List[Int]。一个Nothing是一个Int,因此是正确的。Nothing是任何类型的子类,但是上面的List[Nothing]都不包含任何成员。当我们创建一个包含一个String的List[Nothing]的List,并把它赋值给List[String],会出现什么情况?它会失败,因为Nothing并不是任何类型的父类,并且也不存在Nothing的实例。任何Nothing的容器必然是空的,是Nil。

另一种Nothing的用法是作为不返回函数的返回值。因为Nothing没有任何实例,而函数的返回值必定是一个值,是一个对象,这样定义为Nothing为返回值的函数实际上不可能返回。

四、None

写Java程序的时候,经常会碰到没有有意义的东西可以返回,我们返回null。但返回null有一些问题,调用方必须检查返回值,不然会有NullPointerException的异常。这逼迫我们去check函数的返回值。还有一种解决办法是使用异常,但增加try/catch块,并不是明智的选择。

Scala内置一种解决办法。如果你想返回一个String,但可能有的时候得不到有意义的返回值,我们可以让函数返回Option[String]。

scala> def getAStringMaybe(num: Int): Option[String] = {
| if ( num >= 0 ) Some("A positive number!")
| else None // A number less than 0? Impossible!
| } getAStringMaybe: (Int)Option[String] scala> def printResult(num: Int) = {
| getAStringMaybe(num) match {
| case Some(str) => println(str)
| case None => println("No string!")
| }
| }
printResult: (Int)Unit scala> printResult(100)
A positive number! scala> printResult(-50)
No string!

函数getAStringMaybe返回Option[String]。Option是一个抽象类,它有两个子类:Some和None。因此,初始化一个Option有两种方法。getAStringMaybe返回的只可能是Some[String]或None。Some和None又是Case Class,可以直接用来做模式匹配,很容易用来处理返回值。

类似地,Option[T]作为返回值,意味着调用者可能会收到Some[T]或None。

其实Option作为返回值,并没有比返回null好多少。代码里面充满了Option和模式匹配的代码,也不优雅,所以对待Option还是慎重。

五、Unit

Unit跟java的void一样,表示函数没有返回值。

scala> def doThreeTimes(fn: (Int) => Unit) = {
| fn(1); fn(2); fn(3);
| }
doThreeTimes: ((Int) => Unit)Unit scala> doThreeTimes(println)
1
2
3

Scala中的空的更多相关文章

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

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

  2. Scala 中的函数式编程基础(三)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  3. Scala 中Null, None, Nothing, Nil

    转自:http://blog.csdn.net/bluejoe2000/article/details/30465175 在scala中这四个类型名称很类似,作用确实完全不同的. None是一个obj ...

  4. Programming In Scala笔记-第十七章、Scala中的集合类型

    本章主要介绍Scala中的集合类型,主要包括:Array, ListBuffer, Arraybuffer, Set, Map和Tuple. 一.序列 序列类型的对象中包含多个按顺序排列好的元素,可以 ...

  5. Programming In Scala笔记-第十六章、Scala中的List

    本章主要分析Scala中List的用法,List上可进行的操作,以及需要注意的地方. 一.List字面量 首先看几个List的示例. val fruit = List("apples&quo ...

  6. Programming In Scala笔记-第七章、Scala中的控制结构

    所谓的内建控制结构是指编程语言中可以使用的一些代码控制语法,如Scala中的if, while, for, try, match, 以及函数调用等.需要注意的是,Scala几乎所有的内建控制结构都会返 ...

  7. Scala中的Map使用例子

    Map结构是一种非常常见的结构,在各种程序语言都有对应的api,由于Spark的底层语言是Scala,所以有必要来了解下Scala中的Map使用方法. (1)不可变Map特点: api不太丰富 如果是 ...

  8. 从jvm来看,scala中的@究竟是个什么鬼?@模式匹配符号(scala 词法分析 语法分析常用)

    从jvm来看,scala中的@究竟是个什么鬼? 我也是初步尝试来看jvm的类文件,又是初次来分析@,如不对的地方,请各位指正! 先看一下@ 是个什么? object TestScala { def m ...

  9. 在Scala中免费验证

    优锐课带你详细了解如何在Scala中实施免费的monad验证.抽丝剥茧,细说架构那些事! 由于业务数据的复杂性,已经在数据验证上花费了很多精力.在Scala中,提出了使用应用程序进行验证的方法,并被广 ...

随机推荐

  1. sass学习(2)——关于变量

    定义一个sass变量 可以说,变量是一个编程语言的基础.所以对于sass来说,变量肯定是浓墨重彩的其中一笔,当然函数也是.那我们如何声明定义一个sass的变量呢? 变量的符号$ 变量名称 变量的值 那 ...

  2. HIVE删除表数据

    HIVE只有INSERT,没有UPDATE跟DELETE,所以通过其他的语句产生DETELE效果. 在HDFS上或者本地服务器上新建空的文件XXXXX, 然后执行: LOAD DATA LOCAL I ...

  3. poj 1543 Perfect Cubes(注意剪枝)

    Perfect Cubes Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14901   Accepted: 7804 De ...

  4. Linux定时执行任务命令概述:at和crontab

    本文介绍在Linux下的两种定时执行任务的方法:at命令,以及crontab服务. (1)at命令 假如我们只是想要让特定任务运行一次,那么,这时候就要用到at监控程序了. 设置at命令很简单,指示定 ...

  5. CodeForces 706A Beru-taxi (数学计算,水题)

    题意:给定一个固定位置,和 n 个点及移动速度,问你这些点最快到固定点的时间. 析:一个一个的算距离,然后算时间. 代码如下: #pragma comment(linker, "/STACK ...

  6. hash_map vs unordered_map vs map vs unordered_set

    hash_map vs unordered_map 这两个的内部结构都是采用哈希表来实现.unordered_map在C++11的时候被引入标准库了,而hash_map没有,所以建议还是使用unord ...

  7. MVC4学习过程记录

    终于决定开始尝试Web开发,即是为了工作也是为了自己的兴趣,决定还是从MS的MVC4开始. 首先从Asp.Net MVC4入门指南这个系列开始学习(http://www.cnblogs.com/pow ...

  8. Android Study ING

    http://bbs.csdn.net/topics/370249613 android的tools和adb命令 http://www.u148.net/article/102147.html htt ...

  9. 我的第一个javascript网页作业

    1: <html> 2: <title> 3:   4: </title> 5: <body> 6: <style type="text ...

  10. C++ 不支持模版的分离式编译

    1.C++不支持模版的分离式编译,为什么? C++是分别,单独编译,对于每个cpp文件,预编译为编译单元,这个编译单元是自包含文件,编译的时候,不需要其他的文件,编译好了,生成obj文件,然后连接成e ...