3

Edit: This issue no longer exists in Scala 2.12.6


Original question (for Scala 2.11.7):

Why so strange warning?

scala> null.asInstanceOf[Double]
res0: Double = 0.0

scala> null.asInstanceOf[Double] == null
<console>:11: warning: comparing values of types 
      Double and Null using `==' will always yield !!!!false!!!!
       null.asInstanceOf[Double] == null
                                 ^
res1: Boolean = true //!!!!

scala> 0.0 == null
<console>:11: warning: comparing values of types Double and Null using `==' will always yield false
       0.0 == null
           ^
res2: Boolean = false

scala> null.asInstanceOf[Double] == 0.0
res6: Boolean = true

scala> val a = null.asInstanceOf[Double]
a: Double = 0.0

scala> a == null
<console>:12: warning: comparing values of types Double and Null using `==' will always yield false
       a == null
         ^
res7: Boolean = false

P.S. Same for Int and Long

P.S.2 It's not a duplicate - the problem here is that boxing doesn't happen at all regardless of asInstanceOf (as you can see from my answer) + the warning message is inconsistent

dk14
  • 22,206
  • 4
  • 51
  • 88

2 Answers2

1

Edit: This issue no longer exists in Scala 2.12.6. See pull-request with explanation.


Original answer (for Scala 2.11.7):

null.asInstanceOf[Double] == null compiles to the:

aconst_null
ifnonnull

The val-version compiles to the:

aconst_null
invokestatic unboxToDouble
putfield
aload_0
invokevirtual а
invokestatic boxToDouble
ifnonnull

So compiler just forgets to add unbox/box in the first case

dk14
  • 22,206
  • 4
  • 51
  • 88
  • I am from `Java` started recently with `Scala`, so this statement `null.asInstanceOf[Double]` does not make any sense to me. why on earth this is not a `NullPointerException`? – Vishrant Jul 05 '18 at 20:09
  • @Vishrant Idk, does let's say Java's `Double a = (Double)null` give a `NullPointerException`? :) – dk14 Jul 06 '18 at 02:57
  • No, it's not a NullPointerException, although value of `a` will be `null` – Vishrant Jul 06 '18 at 03:00
  • @Vishrant the whole issue I described is that scala is automatically boxing `null.asIn....` when it's part of assignment (probably for the sake of [unified typing](https://docs.scala-lang.org/tour/unified-types.html)), but forgets to do it otherwise (which is truly inconsistency for old 2.11.7 at least). In any case it shouldn't give runtime exception anyways. – dk14 Jul 06 '18 at 03:06
  • Hmm, but the syntax is weird, calling something on `null` and that won't give `NullPointerExp` – Vishrant Jul 06 '18 at 03:08
  • 1
    @Vishrant And the whole `null` thing in Scala is just for interoperability with Java (and alike), thus a lots of bugs and inconsistencies. Recommended style in Scala is to avoid `null`s overall (by wrapping them with `Option`s). – dk14 Jul 06 '18 at 03:08
  • @Vishrant `a.asInstanceOf[Type]` is equivalent to `(Type)a`. The reason it's that way is to make it stylistically inconvenient and avoid such conversions at all costs. Also probably to easily find those and "kill with fire" :) – dk14 Jul 06 '18 at 03:09
  • Got it. That make sense then. Thx. :) – Vishrant Jul 06 '18 at 03:10
  • Your last statement also answer my other question https://stackoverflow.com/questions/51199570/scala-syntax-null-asinstanceofdouble-why-its-not-a-nullpointerexception – Vishrant Jul 06 '18 at 03:11
  • 1
    on low-level yes. They (quietly) do boxing/unboxing in order to easily return default value for the type. Basically absence of it (in certain cases) contradicts specification itself (maybe they fixed it already, Idk). – dk14 Jul 06 '18 at 03:15
  • @Vishrant just for reference [this pull-request](https://github.com/scala/scala/pull/5176) fixed the issue two years ago. The absence of boxing/unboxing was caused by improper optimization. – dk14 Aug 04 '18 at 06:17
-2

This happens because scala.Double == double in Java, which cannot contain a null value. If you want your desired behaviour you can use java.lang.Double this will be able to store a null value.

val n = null.asInstanceOf[java.lang.Double]
println("null? = " + n)
//null? = null

Another way to prevent the use of double is being more explicit about types

val n: AnyVal = null.asInstanceOf[Double]
println("null? = " + n)
//null? = null

To make things a bit more confusing try this:

println("null? = " + null.asInstanceOf[Double])
//null? = null

This shows the use of double will only happen when your null value is assigned to a val.

I do not have a good explanation for the compiler warning, this warning doesn't seem correct is this specific scenario.

Pim Verkerk
  • 1,066
  • 7
  • 12