如果Int不能为null,则null.asInstanceOf [Int]是什么意思?

Ami*_*ico 32 null scala

作为测试,我写了这段代码:

object Ambig extends App {
  def f( x:Int    ) { println("Int"   ) }
  def f( x:String ) { println("String") }
  f( null.asInstanceOf[Int   ] )
  f( null.asInstanceOf[String] )
  f(null)
}
Run Code Online (Sandbox Code Playgroud)

我期望在最后一次调用f()时遇到错误,说这是不明确的.编译器接受了它,并产生了这个输出:

Int
String
String
Run Code Online (Sandbox Code Playgroud)

现在我猜这与Int不是AnyRef这一事实有关,因此f(null)的唯一f版本是f(x:String).但是,如果Int不能为null,则null.asInstanceOf [Int]是什么意思?repl说它是Int类型:

scala> :type null.asInstanceOf[Int]
Int
Run Code Online (Sandbox Code Playgroud)

但我真的不明白它是如何运作的.毕竟,如果我尝试将一个String转换为一个Int,那么所有的地狱都会崩溃:

scala> "foo".asInstanceOf[Int]
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
        ...
Run Code Online (Sandbox Code Playgroud)

当然这是预期的 - "foo"不能成为Int.但是两者都不能为null,那么为什么将int转换为Int工作呢?想必拳击某种形式,但类型仍然是Int,不能为null ...

我错过了什么?

axe*_*l22 48

转换null为a 的行为Int取决于完成它的上下文.

首先,如果你将a转换null为a Int,它实际上意味着一个盒装整数,其值为null.如果将表达式放在期望类型的上下文中Any(它被转换为Object场景后面,因为在JVM字节码中,没有办法引用具有相同引用的基本类型和引用类型),那么值不会进一步转换 - 这就是println(null.asInstanceOf[Int])打印的原因null.

但是,如果在期望基元Int(Java int)的上下文中使用相同的盒装整数值,它将转换为基元,并且null(作为引用类型的默认值)转换为0(基本类型的默认值) ).

如果一个通用的方法做了这个演员,那么,当然,你得到一个null回来.

但是,如果此方法是专用的,则其返回类型是Int(在这种情况下是原始整数),因此null: Any必须像以前一样将值转换为基元.

因此,运行:

object Test extends App {
  println(null.asInstanceOf[Int])

  def printit(x: Int) = println(x)

  printit(null.asInstanceOf[Int])

  def nullint[T] = null.asInstanceOf[T]

  println(nullint[Int])

  def nullspecint[@specialized(Int) T] = null.asInstanceOf[T]

  println(nullspecint[Int])
}
Run Code Online (Sandbox Code Playgroud)

生产:

null
0
null
0
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 21

事情就是这样:asInstanceOf没有意义.这个方法的作用是告诉编译器STOP MAKING SENSE,并相信你在说什么.

现在,如果你想知道为什么它返回0,那是因为asInstanceOf工作AnyRef,而不是AnyVal.当应用于a时AnyVal,它将使用盒装版本,而盒装null值为0.