【问题标题】:Why does Option.apply throw NPEs for boxed primitives?为什么 Option.apply 会为盒装原语抛出 NPE?
【发布时间】:2015-06-03 09:31:41
【问题描述】:

例如,以下代码将抛出 NPE:

val badData = null: java.lang.Long
val boom: Option[Long] = Option(badData)
java.lang.NullPointerException
  at scala.Predef$.Long2long(Predef.scala:358)
  ... 33 elided

这使得使用返回盒装原语的 Java API 变得困难。

请注意,在这个愚蠢的示例中,可以只从 boom 中删除类型声明,并且代码将运行而不会出错,但在一个更现实的示例中,这可能是不可能的/不容易的。例如:

MyCaseClass(record getValue m.ID, Option(record getValue m.USER))

记录从外部来源提取数据。

【问题讨论】:

    标签: scala


    【解决方案1】:

    问题在于,在您的第二行 boom 被声明为 Scala Long,因此从 java.lang.LongLong 发生了隐式类型转换,因此是 NPE。

    只需确保您使用的是正确的 Java Long 或 Scala Long 类型,并且不会调用隐式类型转换。所以MyCaseClass 应该有Option[java.lang.Long] 作为它的类型。如果您想解决这个问题,您可以在调用 Option.apply 之前显式键入它,然后将其映射到正确的 Scala 类型:

    MyCaseClass(Option(badData: java.lang.Long).map(_.toLong))

    这是我的 REPL 代码:

    scala> val badData = null: java.lang.Long
    badData: Long = null
    
    scala> val boom: Option[Long] = Option(badData)
    java.lang.NullPointerException
      at scala.Predef$.Long2long(Predef.scala:358)
      ... 33 elided
    
    scala> val boom: Option[java.lang.Long] = Option(badData)
    boom: Option[Long] = None
    
    scala> case class MyCaseClass(l: Option[Long])
    defined class MyCaseClass
    
    scala> MyCaseClass(Option(badData: java.lang.Long).map(_.toLong))
    res3: MyCaseClass = MyCaseClass(None)
    

    【讨论】:

    • 啊,有道理,虽然编译器不够聪明,无法自己处理,这很烦人。
    猜你喜欢
    • 1970-01-01
    • 2011-10-10
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    相关资源
    最近更新 更多