如何在Scala中正确使用asInstanceOf

ila*_*ngo 12 scala

我一直在玩基本的Scala数据类型.我注意到这个scala.AnyasInstanceOf[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) 
             }

         }
Run Code Online (Sandbox Code Playgroud)

我的目标是了解在以下情况下会发生什么(以及为什么):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是123 x是123 Int x是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中的基础知识.我知道这个例子无论如何都不是一个现实世界的例子,但我试图让我的头脑缠绕在基础上.

Aar*_*rup 14

爪哇(和Scala),可以投一个原始doubleint(在Scala的情况下,DoubleInt).在另一方面,你可以不投java.lang.Doublejava.lang.Int.

当你声明Double为a时Any,你明确要求编译器忘记你给它一个Double.因此,为了支持Any接口,编译器将值存储为盒装双(即java.lang.Double).

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

如果T是数值类型(第12.2节),则特别处理测试x.asInstanceOf [T].在这种情况下,强制转换将转换为转换方法x.toT(第12.2.1节)的应用程序.


Nik*_*kov 9

我认为你混淆了"演员"和"转换"这两个词.

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

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