【问题标题】:Why can I assign null to an Option?为什么我可以将 null 分配给选项?
【发布时间】:2013-08-24 21:50:40
【问题描述】:

以下是 Scala 中的有效语句:

scala> var x: Option[Int] = Some(3)
x: Option[Int] = Some(3)

scala> var x: Option[Int] = None
x: Option[Int] = None

以下内容无效:

scala> var x: Option[Int] = 3
<console>:7: error: type mismatch;
 found   : Int(3)
 required: Option[Int]
       var x: Option[Int] = 3

到目前为止,这些例子对我来说是有意义的; Option[T] 类型的值可以是 Some[T] 或 None 类型,因此编译器会阻止您分配这两种类型的值。

然而,Scala 编译器似乎接受了这一点:

scala> val x: Option[Int] = null
x: Option[Int] = null

如果我随后尝试对选项进行模式匹配(例如,如下所示),我会遇到意想不到的失败 - 为什么编译器不通过拒绝 null 的分配来保护我免受这种情况的影响?

x match {
  case Some(y) => println("Number: ", y)
  case None => println("No number")
}

【问题讨论】:

  • 任何引用都可以为空;这只是在 JVM 上运行的不幸后果。
  • 感谢克里斯托弗!我刚刚读到this article,上面写着“当然,这些都不能让你摆脱 null,因为 Scala 非常乐意将 null 分配给任何东西。这有点让整个事情看起来有点毫无意义。”有点令人失望;我一直假设 Option (Some/None) 匹配模式是完整的,但实际上要完整,我想你需要匹配 Some / None / null,并进一步检查你从 Some 获得的值。
  • 在进一步阅读之后,我想我理解得更好了。选项更多的是传达程序员的意图,即某个方法可能返回值或不返回值。如果被调用的代码表现良好,则调用者不需要显式处理 null ,因为调用者并不期望它。正如here 所提到的,“我认识的所有 Scala 开发人员的经验是,NPE 在处理现有 Java 库时大多只是一个问题,因为 Scala 程序员和库会避免它。”

标签: scala


【解决方案1】:

如果您查看Scala class hierarchy,您会发现从AnyRef 派生的所有类都是Null 的超类,并且任何此类超类都可以分配值null。由于Option 就是这样一个类,您可以将Null 分配给它。

请注意SomeNone.type(即None 对象的单例类型)都是Null 的超类,因此null 对其中任何一个都是有效值。

您不能将3 分配给Option,因为3 不是Option 的子类的值(显然)。

【讨论】:

    【解决方案2】:

    你可能想问的问题的答案是这样的:

    惯用的 Scala 永远不会使用 null。空引用的存在纯粹是为了与 Java 和其他 JVM 语言的互操作性。如果你在 Scala 代码中看到null,它应该会立即引起关注。你永远不会错误地使用null,所以编译器警告是不必要的。正如 Daniel Sobral 的回答和 cmets 中所述,编译器无法针对null 提供保护。

    【讨论】:

      猜你喜欢
      • 2011-08-11
      • 2023-01-07
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2019-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多