14

我一直在玩基本的 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) 
             }

         }

我的目标是了解在以下情况下会发生什么(以及为什么):1)从 Any 类型转换为 Int。2) 从 Double 类型转换为 Int 3) 从 String 类型转换为 Int

  1. 在第一种情况下,当我以 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)

  2. 在第二种情况下,我得到以下结果: int is 123 x is 123 Int x is 123

在这种情况下,代码应该产生 ClasscastException,但它没有。那是我的担心。

  1. 在第三种情况下,我得到一个 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)

通过这个示例,我的目标是了解在 Scala 中进行转换的基础知识。我知道这个例子无论如何都不是真实世界的例子,但我试图让我的头脑围绕基础知识。

4

3 回答 3

15

Java(和 Scala)允许您将原语double转换为int(在 Scala 的情况下Double为 to Int)。另一方面,您不能java.lang.Double转换为java.lang.Int.

当您将 声明Double为时Any,您是在明确要求编译器忘记您给了它一个Double. 因此,为了支持该Any接口,编译器将值存储为装箱双精度(即java.lang.Double)。

这种行为看起来确实令人困惑,但这不是一个错误。根据Scala 语言规范的§12.1 :

如果 T 是数值类型(第 12.2 节),则对测试 x.asInstanceOf[T] 进行特殊处理。在这种情况下,演员表将被转换为转换方法 x.toT(第 12.2.1 节)的应用程序。

于 2012-09-10T21:32:52.627 回答
13

我认为您混淆了“cast”和“convert”这两个术语。

标准转换方法开头to,例如20d.toInt将类型的值转换20为类型Double的值 20 Int

asInstanceOf另一方面是一种特殊的类型铸造方法。它所做的只是通知编译器该值是其参数中指定的类型,如果在运行时调用此方法的值与您在类型参数中指定的值不匹配,则会引发异常。即在a.asInstanceOf[B]提供的值中a必须是一个类型B或从它继承 - 否则你会得到一个异常。

于 2012-09-10T20:19:16.980 回答
0

Just done more tests(compiled and run), I think this may be from one bug of asInstanceOf, it won't do cast.

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

                                 ^ 

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
于 2016-08-02T03:43:19.543 回答