【问题标题】:scala: assign null to primitivescala:将null分配给原语
【发布时间】:2017-08-27 08:56:36
【问题描述】:

我正在尝试将 null 分配给像这样的 Double 变量:

var foo = 0.0
foo = null

但是,这会产生一个错误,即 null 不能隐式转换为 Double

所以我这样做了:

foo = null.asInstanceOf[Double]

但是 foo 的新值是 0.0

如何将值设置为 null?

【问题讨论】:

标签: scala


【解决方案1】:

你不应该在 Scala 中使用 null,而是专门看看 Option, Option[Double]

val foo = Some(0.0)
foo = Option.empty[Double]

甚至 Java 也引入了可选值,而不是 null。

https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html http://www.scala-lang.org/api/2.7.4/scala/Option.html

【讨论】:

  • 如果我将 foo 设置为 None,我会得到“None.type 不符合预期值 Some[Double]”。如果我将它设置为 null,它会编译。现在如何从 Some[Double] 中检索值?如果我做 foo getOrElse(null) 我得到一个 nullPointerException。
  • 试试 Option.empty[Double]
  • foo 的类型在这里被推断为 Some[Double] 这不是你想要的,因为它不允许 None。您需要添加类型注释Option[Double] 或使用Option(0.0) 而不是Some(0.0)。 foo 在这里也需要是 var 而不是 val。
  • 这个答案不完整,不能编译,如上所述
【解决方案2】:

你不能。 Double 是值类型,只能将null 分配给引用类型。相反,Scala 编译器将 null 替换为默认值 0.0。

查看SLS 4.2中的默认值:

default  type
0        Int or one of its subrange types
0L       Long
0.0f     Float
0.0d     Double
false    Boolean

您也不能将 Java 原语分配给 null。虽然 Scala 的 Double 并不是真正的原始类型(它实际上是 Scala 中的一个类),但它需要在 Java 字节码中编译成 double。相反,如果你想表示一个完全缺失的值,你应该使用Option[Double],并尝试从不在Scala中使用null

【讨论】:

  • 很好的答案,但我不清楚为什么不在 Scala 中使用 null。您不能将 null 分配给 Option[Double] 吗?
  • @cosmos1990 在任何地方使用null 被认为是不好的做法。您可以将null 分配给Option[Double],但这样做是个坏主意。有很多 blog articles 超出了这个问题的范围,可以帮助解释为什么应该避免空值。
  • 我认为这里禁止使用 null 有点言过其实。 Null 的存在是有充分理由的,就像 void 一样。会不会被滥用?当然,条件表达式也可以。我同意那篇关于替代方案的博客文章,我只是不喜欢像“在任何地方使用 null 都被认为是不好的做法”这样的模糊陈述。
  • 顺便说一下,如果你想使用 Option E.G.对于布尔值,当您想使用类似 null 的构造时,请确保使用 val opt: Option[Boolean] = Option.empty 而不是 val opt: Option[Boolean] = null
  • 我知道这已经很晚了,但我想为上面的absmiths提供一些理论支持。在三元逻辑中,“我不知道”是一个有效的选项,这是数据库中 NULL 以及它与 SQL 语句中其他值组合的各种方式的基础。 Scala 中的 None 并没有取代这一点,因为它意味着该值的不存在是已知的。 Option 是一个很棒的类,因为它可以让您区分“我知道它是空的”和“我不知道它的值”,但 null 仍然有作用。可能 Unknown 应该是 Option 之类的类,但现在不是。
【解决方案3】:

要回答为什么编译器在将 null 分配给 double 变量时会抱怨的问题,您可以通过 scala 类层次结构图轻松理解:

http://docs.scala-lang.org/tutorials/tour/unified-types.html

总之,

  • Double 是 Anyval 的子类
  • null(Null 的一个实例)是 AnyRef 的子类。

所以它们在scala中是不同的类型或类,类似于将List分配给String。

【讨论】:

  • 这个答案非常适合回答为什么不能将 null 分配给实例化为 Double 的变量。但在一个答案中,我想我正在寻找答案的另一半,如何在 Scala 中处理这种情况。
【解决方案4】:

另一种(可能是最简单的)方法是使用 java.lang.Double 代替 scala.Double,并分配给 java.lang.Double.NaN 而不是 null。

那你就可以了

if(foo.isNaN) { work around not a number case } else { usual case }

使用变量时。

我说这可能是最简单的,因为如果您的意图是能够检查 Double 值的 Not-Available(或不存在)状态,否则将变量与通常的 Double 算术 & 运算符一起使用,那么使用 java float 原语比使用别名要简单得多,否则围绕 Option[Double] 的包装类工作。

见:Option[Double] arithmetic operatorsCan float (or double) be set to NaN?

【讨论】:

  • 在切换到 Option 之前,我最初使用了这种方法。像 java.lang.Boolean 这样的 java 对象类型和像 scala.Boolean 这样的 scala“原始”类型之间的交互至少可以说是丑陋的。如果可能的话,我会避免它。
  • @absmiths NaN 是 x86 支持的浮点值,出于某种原因,Scala 的作者选择将其抽象掉。虽然这是执行错误操作(除以 0 等)的结果,但它对于跟踪大型数据集中的 NA 非常方便。我一般不建议放弃 Scala 原语,但 Option 可能是一个尴尬的构造。
猜你喜欢
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2012-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多