字节Scala面试题 --- None跟null的区别
今天参加字节跳动大数据岗位的面试。在开始说明实际面试问题之前,大家可以先思考一个问题:Scala中None跟null的区别是什么?它们之间的关系又是什么?
---------------------分界线:以下是实际面试问题讲解---------------------
如果有一个类A,里面有函数func。存在以下代码
case class A() {
def func: Unit = println("Func in A")}
val a: A = A() // nullval 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