【发布时间】:2014-02-26 22:48:58
【问题描述】:
我有以下代码:
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45).
scala> val z: BigDecimal = null
z: BigDecimal = null
scala> z == null
res0: Boolean = true
看起来不错。不过……
scala> import java.math.{BigDecimal => JBigDecimal}
import java.math.{BigDecimal=>JBigDecimal}
scala> val x: JBigDecimal = null
x: java.math.BigDecimal = null
在REPL中,赋值会抛出NPE:
scala> val y: BigDecimal = x
java.lang.NullPointerException
at scala.math.BigDecimal.toString(BigDecimal.scala:452)
at scala.runtime.ScalaRunTime$.scala$runtime$ScalaRunTime$$inner$1(ScalaRunTime.scala:324)
at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:329)
at scala.runtime.ScalaRunTime$.replStringOf(ScalaRunTime.scala:337)
at .<init>(<console>:10)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
使用惰性变量会出现我主要关心的问题。
scala> lazy val y: BigDecimal = x
y: BigDecimal = <lazy>
scala> y == null
res1: Boolean = false
有什么建议吗?这是最后一个比较一个错误吗? 我考虑过将这两个元素都包装在 Options 中,但我首先想了解为什么会发生这种情况。
此外,比较这两个 BigDecimal 也会导致另一个(可能不同,但相关)异常
scala> z == y
java.lang.NullPointerException
at scala.math.BigDecimal.toLongExact(BigDecimal.scala:411)
at scala.math.BigDecimal$$anonfun$isValidLong$1.apply$mcV$sp(BigDecimal.scala:196)
at scala.math.BigDecimal.noArithmeticException(BigDecimal.scala:211)
at scala.math.BigDecimal.isValidLong(BigDecimal.scala:196)
at scala.math.BigDecimal.equals(BigDecimal.scala:190)
at scala.runtime.BoxesRunTime.equalsNumNum(BoxesRunTime.java:168)
我过去常常因为使用断言而变得更有趣
一个经过修改的更具体的例子:
test("Both cases should be true") {
val x: JBigDecimal = null
val y: JBigDecimal = null
x should be (null)
y should be (null)
x == y should be (true)
val i :BigDecimal = x
val j :BigDecimal = y
i == j should be (true)
}
但是,比较 i == j 时会失败
此外,即使使用选项,通过将 JBigDecimal 隐式转换为 BigDecimal,我仍然可以获得 BigDecimal(null) 实例。
我测试了这个错误报告,当我运行BigDecimalBug 时,它的断言失败了。
到目前为止,我复制的唯一可以正常工作的方法如下:
it("test implicit conversions from null Java BigDecimal to Option[BigDecimal]"){
val x: JBigDecimal = null
val y: JBigDecimal = null
x should be (null)
y should be (null)
x == y should be (true)
val i :BigDecimal = x
val j :BigDecimal = y
implicit def convertJBigDecimalOption(javaBigDecimal: JBigDecimal): Option[BigDecimal] =
Option(javaBigDecimal) map { x => BigDecimal(x.toString) }
val p :Option[BigDecimal] = x
val q :Option[BigDecimal] = y
p should be('empty)
q should be('empty)
}
【问题讨论】: