【发布时间】:2020-03-09 12:23:05
【问题描述】:
val i: java.lang.Integer = null
val o: Option[Int] = Option(i) // This yields Some(0)
将null: java.lang.Integer 转换为Scala Option[Int] 的安全方法是什么?
【问题讨论】:
标签: scala optional scala-java-interop
val i: java.lang.Integer = null
val o: Option[Int] = Option(i) // This yields Some(0)
将null: java.lang.Integer 转换为Scala Option[Int] 的安全方法是什么?
【问题讨论】:
标签: scala optional scala-java-interop
你正在混合 Int 和 java.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
【讨论】:
Option[Integer](i).map(_.intValue) 对我来说似乎最地道,因为它说明了它在做什么。此外,使用-Xlint 查看val o 的警告!
Integer 被推断出来。
forced to :)
这似乎正在发生,因为您正在创建Option,并一步将其转换为Int(@MarioGalic 的answer 解释了为什么会发生这种情况)。
这就是你想要的:
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。我猜它只会保存转换调用。
之前也遇到过同样的问题。 Scala 团队知道这种可疑行为。 似乎改变它会破坏其他地方的东西。 见https://github.com/scala/bug/issues/11236 和https://github.com/scala/scala/pull/5176。
【讨论】:
null 视为一个整数。这大概是 C 的后遗症,可以将 0 分配给指针。但这并不意味着生成的指针是0,所以即使在C 中也不能在两者之间切换。
Integer 很可能来自 Java 代码,因此“不要将 null 视为整数”不是一个可行的建议。我们使用Option.apply 明确检查此整数的可空性。所以我们得到了意外的输出,没有明确地执行任何不安全的操作。
JavaConverters 而不是JavaConversion)
theInteger.intValue()。避免这种崩溃需要额外的运行时检查。在旧版本的 Scala 中,这种转换确实产生了 NPE。它被报告为错误,并已修复为当前行为。我不是 Scala 专家,但我挖掘了 scala-dev#355 和 scala#5176 作为历史背景。