比较null BigDecimal与Java BigDecimal

比较null BigDecimal与Java BigDecimal,java,scala,implicit,Java,Scala,Implicit,我有以下代码: 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 => JBig

我有以下代码:

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)
我过去经常用assert得到这个更有趣的结果

一个经过改造的更具体的例子:

  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)实例

我测试了这个bug报告,当我运行时,它没有通过断言

到目前为止,我复制的唯一工作方法是:

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)
}

之所以发生
NullPointerException
,是因为REPL在val赋值之后调用
toString()
,从而引发异常。这就是为什么它不使用惰性计算抛出异常,因为它不调用
toString()
then

scala.math.BigDecimal
是一个包含
java.math.BigDecimal
的类,但包含空值的
scala.math.BigDecimal
的实例本身并不是空引用。在您的示例中,
(y.bigDecimal==null)
将计算为true

无论如何,
选项
的创建是有原因的,最好使用它,而不是赋值和检查空值

编辑:

这样做:

val x : java.math.BigDecimal = null
BigDecimal(x) == BigDecimal(x)
。。将抛出一个
NullPointerException
,因为
BigDecimal
将不可避免地调用它:

def compare (that: BigDecimal): Int = this.bigDecimal compareTo that.bigDecimal

。。它比较包装的
java.math.BigDecimal
s,并且
compareTo
在找到空值时抛出异常。

我理解所有这些,但没有说明我们现在创建的BigDecimal(空值)在任何时候都会失败,而不是赋值空值。它在求值时不会失败,当调用
toString
时,它会失败。为什么
BigDecimal(null)==null
?我不知道还有哪门课是这样的。无论您是否认为这是一个bug,您都很难在scala语言中获得这样的行为。查看方框untime:168,我们发现:if((yn instanceof ScalaNumber)和&!(xn instanceof ScalaNumber))返回yn.equals(xn);我不明白你的意思
valz:BigDecimal=null
BigDecimal(null)
不同。输入错误,我指的是最后一个示例。z==y
val x : java.math.BigDecimal = null
BigDecimal(x) == BigDecimal(x)
def compare (that: BigDecimal): Int = this.bigDecimal compareTo that.bigDecimal