如何在 Scala 中正确使用 asInstanceOf
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12358426/
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
how to use asInstanceOf properly in Scala
提问by ilango
I have been playing with basic Scala data types. I noticed that the scala.Anyclass defines the method asInstanceOf[T0]: T0from hereThe API has it that it can "Cast the receiver object to be of type T0". Using this method as a starting point, I wanted to investigate casting in Scala. Also, I looked up stackoverflow for other questions on this topic and I came up with thisWith this information in hand, I wrote up a silly program.
我一直在玩基本的 Scala 数据类型。我注意到scala.Any该类asInstanceOf[T0]: T0从这里定义了方法API 有它可以“将接收器对象转换为 T0 类型”。使用这种方法作为起点,我想研究 Scala 中的转换。另外,我在 stackoverflow 上查找了有关此主题的其他问题,并提出了这个有了这些信息,我编写了一个愚蠢的程序。
package com.att.scala
import com.att.scala.Sheltie
object Casting {
//def foo(x: String){
def foo(x: Int) {
println("x is " + x)
//if(x.isInstanceOf[String])
if(x.isInstanceOf[Int])
println("Int x is " + x)
//println("String x is " + x)
}
def entry() {
//val double: Any = 123.123
val double: Double = 123.23
val int = double.asInstanceOf[Int] //exception expected here
//val str: String = "123"
foo(int)
}
}
My goal is to understand what happens (and why) in the following cases: 1) casting from an Any type to an Int. 2) casting from Double type to an Int 3) casting from String to Int
我的目标是了解在以下情况下会发生什么(以及为什么):1)从 Any 类型转换为 Int。2) 从 Double 类型转换为 Int 3) 从 String 转换为 Int
In the first case, I got a run time ClasscastException as below, when I ran the program as - com.att.scala.Casting.entry. The exception is shown below:
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source) at com.att.scala.Casting$.entry(Casting.scala:17)In the second case, I get the following result: int is 123 x is 123 Int x is 123
在第一种情况下,当我将程序运行为 com.att.scala.Casting.entry 时,我得到了一个运行时 ClasscastException,如下所示。异常如下所示:
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source) at com.att.scala.Casting$.entry(Casting.scala:17)在第二种情况下,我得到以下结果: int is 123 x is 123 Int x is 123
In this case, the code is supposed to produce a ClasscastException, but it does not. That is my worry.
在这种情况下,代码应该产生 ClasscastException,但它没有。这就是我的担心。
- In the third case, I get a classcastexception:
- 在第三种情况下,我得到一个 classcastexception:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
at com.att.scala.Casting$.entry(Casting.scala:20)
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
at com.att.scala.Casting$.entry(Casting.scala:20)
With this example,my goal is to get to the very basics of casting in Scala. I know that this example is not a real world example by any means, but I was trying to get my head wrapped around the basics.
通过这个示例,我的目标是了解 Scala 中强制转换的基础知识。我知道这个例子无论如何都不是真实世界的例子,但我试图让我的头脑围绕基础知识。
回答by Aaron Novstrup
Java (and Scala) allows you to cast a primitive doubleto int(in Scala's case, Doubleto Int). On the other hand, you cannot cast java.lang.Doubleto java.lang.Int.
Java(和 Scala)允许您将原语转换double为int(在 Scala 的情况下Double为 to Int)。另一方面,您不能强制转换java.lang.Double为java.lang.Int.
When you declare the Doubleas an Any, you're explicitly asking the compiler to forget that you gave it a Double. Therefore, in order to support the Anyinterface, the compiler is storing the value as a boxed double (i.e., java.lang.Double).
当您将 声明Double为 an 时Any,您明确要求编译器忘记您给它一个Double。因此,为了支持该Any接口,编译器将值存储为装箱双精度值(即java.lang.Double)。
The behavior does seem confusing, but it's not a bug. According §12.1 of the Scala Language Spec:
这种行为看起来确实令人困惑,但这不是错误。根据Scala 语言规范的§12.1 :
The test x.asInstanceOf[T] is treated specially if T is a numeric value type (§12.2). In this case the cast will be translated to an application of a conversion method x.toT (§12.2.1).
如果 T 是数值类型(第 12.2 节),则测试 x.asInstanceOf[T] 会被特殊对待。在这种情况下,强制转换将转换为转换方法 x.toT(第 12.2.1 节)的应用程序。
回答by Nikita Volkov
I think you've confused the terms "cast" and "convert".
我认为您混淆了“cast”和“convert”这两个术语。
The standard conversion methods begin with to, e.g. 20d.toIntwill convert a value 20of type Doublea value 20 of type Int.
标准转换方法以 开头to,例如20d.toInt将转换20类型Double为 20 的值Int。
asInstanceOfon the other hand is a special type casting method. All it does is informs the compiler that the value is of the type specified in its parameter, if during runtime the value on which you call this method does not match with what you specified in the type parameter, you'll get an exception thrown. I.e. in a.asInstanceOf[B]the provided value amust be of a type Bor inherit from it - otherwise you'll get an exception.
asInstanceOf另一方面是一种特殊类型的铸造方法。它所做的只是通知编译器该值属于其参数中指定的类型,如果在运行时调用此方法的值与您在类型参数中指定的值不匹配,则会抛出异常。即在a.asInstanceOf[B]提供的值a必须是一个类型B或从它继承 - 否则你会得到一个异常。
回答by Tianwen Chu
Just done more tests(compiled and run), I think this may be from one bug of asInstanceOf, it won't do cast.
刚刚做了更多的测试(编译并运行),我认为这可能来自 asInstanceOf 的一个错误,它不会进行转换。
The last line command gives me compiling error:
最后一行命令给了我编译错误:
Warning:(46, 38) fruitless type test: a value of type Int cannot also be a S println(listTemp2(1).isInstanceOf[S]) // won't compile
警告:(46, 38) 无用的类型测试:Int 类型的值不能也是 S println(listTemp2(1).isInstanceOf[S]) // 不会编译
^
val listOfS = Some(List(S("i1", "k1", "s1"), S("i2", "k2", "s2")))
val listTemp:Seq[K] = listOfS.get.asInstanceOf[Seq[K]]
val listTemp2:Seq[Int] = listOfS.get.asInstanceOf[Seq[Int]]
println("ListTemp:")
println(listTemp(1)) //print S(i2,k2,s2)
println(listTemp(1).isInstanceOf[S]) // true
println(listTemp(1).isInstanceOf[K]) // false
println(listTemp2(1)) //print S(i2,k2,s2)
println(listTemp2(1).isInstanceOf[Int]) // false
println(listTemp2(1).isInstanceOf[S]) // won't compile

