Scala Option(null)预期为None,但我得到了Some(0)


Answers:


17

你在混Intjava.lang.Integer所以

val i: java.lang.Integer = null
val o: Option[Int] = Option(i)

隐式转换为

val o: Option[Int] = Option(Integer2int(i))

变成

val o: Option[Int] = Option(null.asInstanceOf[Int])

从而

val o: Option[Int] = Some(0)

如果您想使用java.lang.Integer,请写

val o: Option[java.lang.Integer] = Option(i)
// o: Option[Integer] = None

2
最近有人问这个问题,所以这是一个真正的陷阱。也许问题在于推理:Option[Integer](i).map(_.intValue)在我看来,这是最惯用的,因为它说明了正在做什么。另外,还可-Xlint用于查看val o!的警告。
som-snytt

为了避免拳击往返,Integer可以推断出val x:Option [Int] = Option(i).asInstanceOf [Option [Int]] 。
som-snytt,

7

这似乎正在发生,因为您正在创建Option,并将其转换为Int一步(@MarioGalic的答案说明了为什么会发生这种情况)。

这就是您想要的:

scala> val o: java.lang.Integer = null
o: Integer = null

scala> val i: Option[Int] = Option(o).map(_.toInt)
i: Option[Int] = None

scala> val o1: java.lang.Integer = 1
o1: Integer = 1

scala> val i1: Option[Int] = Option(o1).map(_.toInt)
i1: Option[Int] = Some(1)

关于另一个答案,我建议_.intValue。我猜它只保存转换调用。
som-snytt

1

以前也遇到过同样的问题。Scala团队知道这种可疑的行为。似乎更改它会破坏其他地方的东西。见https://github.com/scala/bug/issues/11236https://github.com/scala/scala/pull/5176


2
真正可疑的行为是将其null视为整数。大概这是一个宿醉,可以从该宿醉C分配0给一个指针。但这并不意味着结果的指针是0,因此甚至在C
提姆

Integer最有可能来自Java代码,因此“不要将null视为整数”不是可行的建议。然后,我们使用明确检查此Integer是否可为空Option.apply。因此,我们得到了意外的输出,没有明确地执行任何不安全的操作。
simpadjo

关键是,当根本原因是Java时,您不能责怪Scala的“可疑行为”。可行的建议是将Java类型显式转换为等效的Scala类型,而不是使用隐式转换。(因此,JavaConverters而不是JavaConversion
Tim

1
好吧,我可以并且也应该责怪Scala在这种情况下没有发出编译错误/警告。甚至运行时崩溃也会更好。甚至仅在我公司,就有2位在Scala中有5年以上经验的开发人员遇到了这个问题。
simpadjo

1
@Tim只需调用,很容易导致运行时崩溃theInteger.intValue()。避免崩溃是需要额外的运行时检查的成本。在旧版本的Scala中,这种转换的确产生了NPE。它被报告为错误,并已修复为当前行为。我不是Scala专家,但是我挖出了scala-dev#355scala#5176作为历史背景。
合金
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.