vlambda博客
学习文章列表

字节Scala面试题 --- None跟null的区别

今天参加字节跳动大数据岗位的面试。在开始说明实际面试问题之前,大家可以先思考一个问题:Scala中None跟null的区别是什么?它们之间的关系又是什么?







---------------------分界线:以下是实际面试问题讲解---------------------


如果有一个类A,里面有函数func。存在以下代码

case class A() {
def func: Unit = println("Func in A")

}

val a: A = A() // null
val b = Some(a)


如何用b正确的使用func函数?


以下两种写法在a = null时都可以避免NullPointerException的出现:


第一种写法。因为b是Some类型,所以直接用Some来匹配即可,x其实就是匹配的a。若a = null时,匹配出来x也等于null

b match {
case Some(x) =>
if (x == null) {
println("null")
} else {
x.func
}

}


第二种写法。可以先让特殊情况null匹配了之后,再匹配其余的情况

b match {
case Some(null) =>
case Some(x) => x.func
}


那么请问如果将第二种写法中的Some(null)改成None是否可行呢?

b match {

case None => // 替换Some(null)为None

 case Some(x) => x.func

}


我们来试着编译一下

pattern type is incompatible with expected type;
found : None.type
required: Some[A]
case None =>


我们可以看到b的匹配类型会报错。这是因为Some跟None其实都是Option的子类。这里b的类型的Some,与None同级。


由此可以证明Some(null)并不等于None。

查看None的Scala源码可以看到

case object None extends scala.Option[scala.Nothing] with scala.Product with scala.Serializable {
def get : scala.Nothing = { /* compiled code */ }
}

null是Null里的唯一对象,Null是所有AnyRef的子类。None是一个继承了Option[Nothing]的单例类,而Nothing是所有类的子类(包括null);见下Scala类的继承树状图

至此,我们可以推断出null跟None之间的关系应该为:

Option[null] == None

根据以上所述,在实际的场景中我们一般不会定义b = Some(a),而是会定义 b = Option(a);因为用Option才能更好的用Some跟None来匹配(如下图):

case class A() {
def func: Unit = println("Func in A")
}
val a: A = null
val b = Option(a) // Option而不是Some
b match {
case Some(x) => x.func
case None => println("a is null")
}


ref:

https://www.cnblogs.com/gispathfinder/p/12701122.html

http://www.voidcn.com/article/p-bfmdyrts-bsy.html

https://blog.csdn.net/bluejoe2000/article/details/30465175