I have been playing with basic Scala data types. I noticed that the scala.Any
class defines the method asInstanceOf[T0]: T0
from here The 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 * for other questions on this topic and I came up with this With this information in hand, I wrote up a silly program.
我一直在尝试基本的Scala数据类型。我注意到scala。任何类都定义了asInstanceOf[T0]: T0:从这里API可以“将receiver对象转换为T0类型”。以这种方法为出发点,我想研究Scala中的强制转换。另外,我查了*关于这个话题的其他问题,我找到了这个信息,我写了一个愚蠢的程序。
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)从任意类型转换为Int类型;2)从双类型转换为Int类型;3)从字符串转换为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:
在第一种情况下,当我以- com.att. scala.cast. 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)
. lang。ClassCastException:. lang。不能将Double强制转换为java.lang。在scala.run .runtime. boxesruntime . unboxtoint(未知来源)的整数。
-
In the second case, I get the following result: int is 123 x is 123 Int x is 123
在第二种情况下,我得到如下结果:int = 123 x = 123 int x = 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)
. lang。ClassCastException:. lang。字符串不能被转换为java.lang。在scala.runtime.BoxesRunTime.unboxToInt(未知源)at . att.scala.cast $.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中的基本转换。我知道这个例子并不是一个真实的例子,但是我试图让我的头脑被基本的东西包围。
3 个解决方案
#1
14
Java (and Scala) allows you to cast a primitive double
to int
(in Scala's case, Double
to Int
). On the other hand, you cannot cast java.lang.Double
to java.lang.Int
.
Java(和Scala)允许您将一个原语double转换为int(在Scala的例子中,是double转换为int)。另一方面,您不能强制转换java.lang。双java.lang.Int。
When you declare the Double
as an Any
, you're explicitly asking the compiler to forget that you gave it a Double
. Therefore, in order to support the Any
interface, the compiler is storing the value as a boxed double (i.e., java.lang.Double
).
当您将Double声明为Any时,您显式地要求编译器忘记您给了它一个Double。因此,为了支持任何接口,编译器将该值存储为一个盒装的double(即java.lang.Double)。
The behavior does seem confusing, but it's not a bug. According §12.1 of the Scala Language Spec:
这种行为看起来确实令人困惑,但它不是一个bug。根据§12.1 Scala语言的规范:
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).
测试x。asInstanceOf[T]治疗尤其是T是一个数值类型(§12.2)。在这种情况下,转换将被转换为转换方法x的应用程序。合计(§12.2.1)。
#2
7
I think you've confused the terms "cast" and "convert".
我想你把“cast”和“convert”这两个词搞混了。
The standard conversion methods begin with to
, e.g. 20d.toInt
will convert a value 20
of type Double
a value 20 of type Int
.
标准的转换方法以to开头,例如20d。toInt将转换类型为20的值Double,类型为20的值Int。
asInstanceOf
on 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 a
must be of a type B
or inherit from it - otherwise you'll get an exception.
另一方面,asInstanceOf是一种特殊的类型铸造方法。它所做的就是通知编译器该值是其参数中指定的类型,如果在运行时调用此方法的值与类型参数中指定的值不匹配,则会抛出异常。即在一个。asInstanceOf[B]提供的值a必须属于B类型或继承自B类型——否则您将得到一个异常。
#3
0
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
#1
14
Java (and Scala) allows you to cast a primitive double
to int
(in Scala's case, Double
to Int
). On the other hand, you cannot cast java.lang.Double
to java.lang.Int
.
Java(和Scala)允许您将一个原语double转换为int(在Scala的例子中,是double转换为int)。另一方面,您不能强制转换java.lang。双java.lang.Int。
When you declare the Double
as an Any
, you're explicitly asking the compiler to forget that you gave it a Double
. Therefore, in order to support the Any
interface, the compiler is storing the value as a boxed double (i.e., java.lang.Double
).
当您将Double声明为Any时,您显式地要求编译器忘记您给了它一个Double。因此,为了支持任何接口,编译器将该值存储为一个盒装的double(即java.lang.Double)。
The behavior does seem confusing, but it's not a bug. According §12.1 of the Scala Language Spec:
这种行为看起来确实令人困惑,但它不是一个bug。根据§12.1 Scala语言的规范:
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).
测试x。asInstanceOf[T]治疗尤其是T是一个数值类型(§12.2)。在这种情况下,转换将被转换为转换方法x的应用程序。合计(§12.2.1)。
#2
7
I think you've confused the terms "cast" and "convert".
我想你把“cast”和“convert”这两个词搞混了。
The standard conversion methods begin with to
, e.g. 20d.toInt
will convert a value 20
of type Double
a value 20 of type Int
.
标准的转换方法以to开头,例如20d。toInt将转换类型为20的值Double,类型为20的值Int。
asInstanceOf
on 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 a
must be of a type B
or inherit from it - otherwise you'll get an exception.
另一方面,asInstanceOf是一种特殊的类型铸造方法。它所做的就是通知编译器该值是其参数中指定的类型,如果在运行时调用此方法的值与类型参数中指定的值不匹配,则会抛出异常。即在一个。asInstanceOf[B]提供的值a必须属于B类型或继承自B类型——否则您将得到一个异常。
#3
0
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