scala中的option[T]、Any、Nothing、Null、null、Nil、None、Some和Unit

scala中的option[T]、Any、Nothing、Null、null、Nil、None和Unit

1 Option[T] 、 None 和 Some

Option定义:

package scala
@scala.SerialVersionUID(value = -114498752079829388)
sealed abstract class Option[+A]() extends scala.AnyRef with scala.Product with scala.Serializable {
  ...
}
object Option extends scala.AnyRef with scala.Serializable {
  implicit def option2Iterable[A](xo : scala.Option[A]) : scala.Iterable[A] = { /* compiled code */ }
  def apply[A](x : A) : scala.Option[A] = { /* compiled code */ }
  def empty[A] : scala.Option[A] = { /* compiled code */ }
}

Option[T]主要是用来避免NullPointerException异常的(Option本身是一个容器)


object Test {
  def main(args: Array[String]): Unit = {
    val option1: Option[Int] = Some(2018)
    val option2: Option[Int] = None

    val v1 = option1.getOrElse(0)
    println(v1)//输出:2018
    val v2 = option2.getOrElse(0)
    println(v2)//输出: 0

    //我们明确知道option1是有值的
    val v3 = option1.get
    println(v3)//输出:2018

    val map:Map[Int,String] = Map(1 -> "aaa", 2 -> "bbbb", 3 -> "cccc")
    //根据key获取map中的值,map中的value都是一个Option
    val v4:Option[String] = map.get(1)
    println(v4)//输出:Some(aaa)
    //根据key获取map中的值,并求出值的长度
    println(map.get(1).getOrElse("").length())//输出:3
    println(map.get(10).getOrElse("").length())//输出:0
    println(map.get(10))//输出:None
    //检测Option容器中的元素是否为 None
    println(map.get(1).isEmpty)//输出:false
    println(map.get(10).isEmpty)//输出:true
    
  }
}

Option定义了getOrElse方法,在获取容器中的值是如果有返回容器中的值,如果没有就返回给定的值,这一点和Java8的一样。

Option定义了get方法,直接获取容器中的元素,该操作不安全,可能会遇到None,None调用get就会出现空指针异常

Option定义了isEmpty方法,可以判断容器中是不是None

Option的apply()方法可以返回None/Some可知None或Some必定是Option的子类,None与Some源码

None 源码

package scala
@scala.SerialVersionUID(value = 5066590221178148012)
case object None extends scala.Option[scala.Nothing] with scala.Product with scala.Serializable {
  def isEmpty : scala.Boolean = { /* compiled code */ }
  def get : scala.Nothing = { /* compiled code */ }
}



Some源码
package scala
@scala.SerialVersionUID(value = 1234815782226070388)
final case class Some[+A](val value : A) extends scala.Option[A] with scala.Product with scala.Serializable {
  def isEmpty : scala.Boolean = { /* compiled code */ }
  def get : A = { /* compiled code */ }
  @scala.deprecated("Use .value instead.", "2.12.0")
  def x : A = { /* compiled code */ }
}

Option的常用方法:

序号 方法及描述
1

def get: A

获取可选值

2

def isEmpty: Boolean

检测可选类型值是否为 None,是的话返回 true,否则返回 false

3

def productArity: Int

返回元素个数, A(x_1, ..., x_k), 返回 k

4

def productElement(n: Int): Any

获取指定的可选项,以 0 为起始。即 A(x_1, ..., x_k), 返回 x_(n+1) , 0 < n < k.

5

def exists(p: (A) => Boolean): Boolean

如果可选项中指定条件的元素存在且不为 None 返回 true,否则返回 false。

6

def filter(p: (A) => Boolean): Option[A]

如果选项包含有值,而且传递给 filter 的条件函数返回 true, filter 会返回 Some 实例。 否则,返回值为 None 。

7

def filterNot(p: (A) => Boolean): Option[A]

如果选项包含有值,而且传递给 filter 的条件函数返回 false, filter 会返回 Some 实例。 否则,返回值为 None 。

8

def flatMap[B](f: (A) => Option[B]): Option[B]

如果选项包含有值,则传递给函数 f 处理后返回,否则返回 None

9

def foreach[U](f: (A) => U): Unit

如果选项包含有值,则将每个值传递给函数 f, 否则不处理。

10

def getOrElse[B >: A](default: => B): B

如果选项包含有值,返回选项值,否则返回设定的默认值。

11

def isDefined: Boolean

如果可选值是 Some 的实例返回 true,否则返回 false。

12

def iterator: Iterator[A]

如果选项包含有值,迭代出可选值。如果可选值为空则返回空迭代器。

13

def map[B](f: (A) => B): Option[B]

如果选项包含有值, 返回由函数 f 处理后的 Some,否则返回 None

14

def orElse[B >: A](alternative: => Option[B]): Option[B]

如果一个 Option 是 None , orElse 方法会返回传名参数的值,否则,就直接返回这个 Option。

15

def orNull

如果选项包含有值返回选项值,否则返回 null。

2 Any

Any是abstract类,它是Scala类继承结构中最底层的。所有运行环境中的Scala类都是直接或间接继承自Any这个类,它就是其它语言(.Net,Java等)中的Object。

Any 处于类型结构树的根部位置,Any 没有父类,但有三个子类:

 AnyVal, 价值类型和价值类的父类。
 AnyRef,所有引用类型的父类。
•通用特征(universal trait)。

AnyVal 有九个具体子类,称为值类型。其中七个是数字值类型:Byte、Char、Short、Int、Long、Float 和Double。余下的两个是非数字值类型,Unit 和Boolean。

除AnyVal及其子类外,其他类型均为引用类型。它们派生自AnyRef,AnyRef 是java.lang.Object的别名。在Java 的对象模型中,Object 并没有一个封装了原生类型和引用类型的父类,因为Java 对原生类型做了特殊处理。

3.Nothing

Nothing是所有其他类型的子类

Nothing 在Java 中没有类似的概念,但它填补了存在于Java 类型系统中的空白。Nothing 在编译器里的实现相当于以下声明:

package scala
abstract final class Nothing extends Any

Nothing 实际上继承了Any。根据类型系统里的构造规则,Nothing 是所有其他类型的子类,无论是引用类型还是值类型。换句话说,Nothing 继承了所有一切(everything),这让它的名字听起来很奇怪。

Nothing 没有实例,Nothing 为类型系统提供了两种功能:

1、用来当做Nil的类型List[Nothing]

package scala.collection.immutable
object Nil extends List[Nothing] with Product with Serializable

 Nil表示一个空的list,与list中的元素类型无关,他可以同时表示List[任意类型]的空集合。

2、Nothing 用来表示终止程序,非正常类型的返回值类型

我们可以临时调用??? 方法来定义其他的方法,使得方法定义完整,并通过编译。但如果调用该方法,就会抛出异常。以下是??? 的定义:

package scala
object Predef {
...
def ??? : Nothing = throw new NotImplementedError
...
}

4.Null与null

Null 对于大多数语言而言是个熟悉的概念。尽管这些语言通常并没有定义Null 类型,仅仅定义了关键字null,用于向引用变量赋值,表示该变量实际上没有值。Null 在编译器里的实现相当于以下声明:

package scala
abstract final class Null extends AnyRef

该声明不允许子类派生以及创建实例,但运行时环境提供了一个实例,就是我们最熟悉的、最喜爱、最可恶的null,我们在创建实例时仅仅是想声明一下变量,暂时不创建实例,这是很容易想到null对象,有了它我们就可以顺利编写程序了,所以null是我们最熟悉、最喜爱的实例,所谓乐极生悲,爱极必反,null也不例外,他也是空指针的万恶之源,所以他也是最可恶的实例。

Null 被明确定义为AnyRef 的一个子类型,但它也是所有AnyRef 类型的子类型。这是类型系统允许你用null 给任何引用类型赋值的正常做法。另一方面,因为null 不是AnyVal 的子类型,所以不可以用null 给Int 赋值。于是,Scala 的null 与Java 的null 完全相同,因为它必须与Java 的null 共存于JVM。否则,Scala 会破坏null 的概念,引起很多潜在的bug。

5、Nil

Nil是Scala声明一个空列表的专用类型,它是继承了List[Nothing] 的对象,它只需要一个实例,因为它没有携带任何“状态”(元素)。由于List 的类型参数是协变的,对于任意类型A,Nil 是所有List[A] 的子类型。所以,我们不需要分开Nil[A] 实例,一个实例就够了。

6、Unit

先不多说,源码在此

package scala
final abstract class Unit() extends scala.AnyVal {
  override def getClass() : _root_.scala.Predef.Class[scala.Unit] = { /* compiled code */ }
}
object Unit extends scala.AnyRef with scala.AnyValCompanion {
  def box(x : scala.Unit) : scala.runtime.BoxedUnit = { /* compiled code */ }
  def unbox(x : java.lang.Object) : scala.Unit = { /* compiled code */ }
  override def toString() : java.lang.String = { /* compiled code */ }
}

Unit是函数和方法的返回值类型,表示没有返回值。这一点和java的void有点像,但不等同于java的void,因为java的void可以返回null。

猜你喜欢

转载自blog.csdn.net/u014646662/article/details/84063450