首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >比较Java BigDecimal中的空BigDecimal

比较Java BigDecimal中的空BigDecimal
EN

Stack Overflow用户
提问于 2014-02-03 20:33:34
回答 1查看 4.6K关注 0票数 0

我有以下代码:

代码语言:javascript
复制
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

看起来挺好的。然而..。

代码语言:javascript
复制
scala> import java.math.{BigDecimal => JBigDecimal}
import java.math.{BigDecimal=>JBigDecimal}

scala> val x: JBigDecimal = null
x: java.math.BigDecimal = null

在REPL中,赋值将抛出NPE:

代码语言:javascript
复制
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)

使用Lazy变量将呈现我主要关心的问题。

代码语言:javascript
复制
scala> lazy val y: BigDecimal = x
y: BigDecimal = <lazy>

scala> y == null
res1: Boolean = false

有什么建议吗?最后一次比较是一个bug吗?我考虑过将这两个元素都包含在选项中,但我首先想知道为什么会发生这种情况。

此外,比较这两个BigDecimals还会导致另一个异常(可能不同,但相关)

代码语言:javascript
复制
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)

我过去经常使用assert来获得更多有趣的东西。

一个修改过的,更具体的例子:

代码语言:javascript
复制
  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(空)实例。

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

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

代码语言:javascript
复制
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)
}
EN

回答 1

Stack Overflow用户

发布于 2014-02-03 21:22:16

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

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

在任何情况下,Option的创建都是有原因的,使用它比赋值和检查null要好得多。

编辑:

像这样做一些事情:

代码语言:javascript
复制
val x : java.math.BigDecimal = null
BigDecimal(x) == BigDecimal(x)

。。将抛出NullPointerException,因为BigDecimal将不可避免地调用以下代码:

代码语言:javascript
复制
def compare (that: BigDecimal): Int = this.bigDecimal compareTo that.bigDecimal

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21527555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档