scala 如果 Int 不能为 null,null.asInstanceOf[Int] 是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10749010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
If an Int can't be null, what does null.asInstanceOf[Int] mean?
提问by AmigoNico
As a test, I wrote this code:
作为测试,我写了这段代码:
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)
}
I was expecting to get an error on that last invocation of f(), saying that it was ambiguous. The compiler accepted it, and produced this output:
我期待在最后一次调用 f() 时得到一个错误,说它不明确。编译器接受了它,并产生了这个输出:
Int
String
String
Now I'm guessing that this has to do with the fact that Int is not an AnyRef, so the only version of f that works for f(null) is f(x:String). But then, if an Int can't be null, what does null.asInstanceOf[Int] mean? The repl says it's of type Int:
现在我猜这与 Int 不是 AnyRef 的事实有关,所以唯一适用于 f(null) 的 f 版本是 f(x:String)。但是,如果 Int 不能为 null,那么 null.asInstanceOf[Int] 是什么意思?repl 说它是 Int 类型:
scala> :type null.asInstanceOf[Int]
Int
but I don't really see how that works. After all, if I try to cast a String to an Int, all hell breaks loose:
但我真的不明白这是如何工作的。毕竟,如果我尝试将 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)
...
Of course that's to be expected -- "foo" can't be made into an Int. But neither can null, so why does casting null to an Int work? Presumably boxing in some form, but the type is still Int, which can't be null...
当然,这是意料之中的——“foo”不能变成 Int。但是两者都不能为 null,那么为什么将 null 转换为 Int 会起作用呢?大概是某种形式的装箱,但类型仍然是Int,不能为空...
What am I missing?
我错过了什么?
回答by axel22
The behaviour of casting nullto an Intdepends on the context in which it is done.
强制转换null为 an的行为Int取决于完成它的上下文。
First of all, if you cast a nullto an Int, it actually means a boxed integer, whose value is null. If you put the expression in a context where the expected type is Any(which is translated to Objectbehind the scene, because in the JVM bytecode, there is no way to refer to a primitive type and a reference type with the same reference), then this value is not converted further - that is why println(null.asInstanceOf[Int])prints null.
首先,如果将 a 强制转换null为 an Int,它实际上表示一个装箱整数,其值为null。如果你把表达式放在预期类型所在的上下文中Any(它被翻译成Object幕后,因为在JVM字节码中,没有办法引用一个原始类型和一个引用类型相同的引用),那么这个value 不会进一步转换 - 这就是为什么println(null.asInstanceOf[Int])打印null.
However, if you use this same boxed integer value in a context where a primitive Int(Java int) is expected, it will be converted to a primitive, and nullis (as a default value for reference types) converted to 0(a default value for primitive types).
但是,如果您在需要基元Int(Java int)的上下文中使用相同的装箱整数值,它将被转换为基元,并且null(作为引用类型的默认值)转换为0(基元类型的默认值) )。
If a generic method does this cast, then, naturally, you get a nullback.
如果泛型方法执行此转换,那么您自然会得到null回报。
However, if this method is specialized, then its return type is Int(which is a primitive integer in this case), so the null: Anyvalue has to be converted to a primitive, as before.
然而,如果这个方法是专门的,那么它的返回类型是Int(在这种情况下是一个原始整数),所以这个null: Any值必须像以前一样转换为一个原始值。
Hence, running:
因此,运行:
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])
}
produces:
产生:
null
0
null
0
回答by Daniel C. Sobral
Here's the thing: asInstanceOfdoesn't have to make sense. What this method does is to tell the compiler to STOP MAKING SENSE, and trust what you are saying.
事情是这样的:asInstanceOf没有意义。这个方法的作用是告诉编译器停止制作,并相信你所说的。
Now, if you want to know why it returns 0, that's because asInstanceOfworks on AnyRef, not on AnyVal. When applied to an AnyVal, it will use the boxed version instead, and a boxed nullhas value 0.
现在,如果您想知道它为什么返回 0,那是因为asInstanceOf适用于AnyRef,而不是适用于AnyVal。当应用于 an 时AnyVal,它将使用盒装版本,而盒装版本的null值为 0。
回答by dhg
It looks like it's just automatically converting it to zero:
看起来它只是自动将其转换为零:
scala> null.asInstanceOf[Int]
res0: Int = 0
And, of course, 0, unlike null, can be an Int.
当然,与 null 不同,0 可以是Int.
回答by Chen
First, we all agree that we cannot assign nullto scala.Intas documented in http://www.scala-lang.org/api/current/index.html#scala.Null
首先,我们都同意,我们不能分配null给scala.Int作为记录在http://www.scala-lang.org/api/current/index.html#scala.Null
Second, why when we do println(null.asInstanceOf[Int]), it gives null?
This is because of the implementation of println. It eventually calls java String.valueOfmethod, which is
其次,为什么当我们这样做时println(null.asInstanceOf[Int]),它给出了null?
这是因为 println 的实现。它最终调用javaString.valueOf方法,即
return (obj == null) ? "null" : obj.toString();
If you do a null.asInstanceOf[Int] == nullin the shell, it will return true, but it gives an opposite warning that "comparing values of types Int and Null using `==' will always yield false". I think this might be a problem in scala's type erasure.
如果null.asInstanceOf[Int] == null在 shell 中执行 a ,它将返回 true,但它会给出相反的警告,即“使用 `==' 比较 Int 和 Null 类型的值将始终产生 false”。我认为这可能是 scala 类型擦除的问题。
Doing a printlnonly needs a scala.Any type, so the casting of null.asInstanceOf[Int]actually has not happen yet. So we just need to remember that when you assign null.asInstanceOf[Int]to an Int, the cast happens at runtime based on Scala's erasure semantics, and it assigns 0 to it.
做 aprintln只需要一个 scala.Any 类型,所以null.asInstanceOf[Int]实际上还没有发生转换。所以我们只需要记住,当你分配null.asInstanceOf[Int]给一个 Int 时,转换发生在运行时基于 Scala 的擦除语义,它分配给它 0。
By the way, you can still do a f(null) without any compilation error because scala is doing an implicit conversion for you
顺便说一句,您仍然可以在没有任何编译错误的情况下执行 af(null) 因为 scala 正在为您进行隐式转换
null -> java.lang.Integer -> scala.Int
However, you will see it blows up at run time.
但是,您会看到它在运行时爆炸。

