简体   繁体   English

如何在Scala中正确使用asInstanceOf

[英]how to use asInstanceOf properly in Scala

I have been playing with basic Scala data types. 我一直在玩基本的Scala数据类型。 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". 我注意到scala.Any类定义方法asInstanceOf[T0]: T0这里 API有它可以“将接收器对象转换为T0类型”。 Using this method as a starting point, I wanted to investigate casting in Scala. 使用此方法作为起点,我想调查Scala中的强制转换。 Also, I looked up stackoverflow for other questions on this topic and I came up with this With this information in hand, I wrote up a silly program. 另外,我查看了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. 我的目标是了解在以下情况下会发生什么(以及为什么):1)从Any类型转换为Int。 2) casting from Double type to an Int 3) casting from String to Int 2)从Double类型转换为Int 3)从String转换为Int

  1. In the first case, I got a run time ClasscastException as below, when I ran the program as - com.att.scala.Casting.entry. 在第一种情况下,当我运行程序为 - com.att.scala.Casting.entry时,我得到了一个运行时ClasscastException,如下所示。 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)

  2. 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. 在这种情况下,代码应该产生ClasscastException,但它不会。 That is my worry. 这是我的担心。

  1. 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)

With this example,my goal is to get to the very basics of casting in Scala. 在这个例子中,我的目标是了解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. 我知道这个例子无论如何都不是一个现实世界的例子,但我试图让我的头脑缠绕在基础上。

Java (and Scala) allows you to cast a primitive double to int (in Scala's case, Double to Int ). Java(和Scala)允许您将原始doubleint (在Scala的情况下, DoubleInt )。 On the other hand, you cannot cast java.lang.Double to java.lang.Int . 另一方面,您无法将java.lang.Doublejava.lang.Int

When you declare the Double as an Any , you're explicitly asking the compiler to forget that you gave it a Double . 当你将Double声明为Any ,你明确要求编译器忘记你给它一个Double Therefore, in order to support the Any interface, the compiler is storing the value as a boxed double (ie, java.lang.Double ). 因此,为了支持Any接口,编译器将值存储为boxed double(即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). 如果T是数值类型(第12.2节),则特别处理测试x.asInstanceOf [T]。 In this case the cast will be translated to an application of a conversion method x.toT (§12.2.1). 在这种情况下,强制转换将转换为转换方法x.toT(第12.2.1节)的应用程序。

I think you've confused the terms "cast" and "convert". 我认为你混淆了“演员”和“转换”这两个词。

The standard conversion methods begin with to , eg 20d.toInt will convert a value 20 of type Double a value 20 of type Int . 标准的转换方法开始to ,例如20d.toInt将转换值20Double类型的值20 Int

asInstanceOf on the other hand is a special type casting method. 另一方面, asInstanceOf是一种特殊类型的铸造方法。 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. 它只是通知编译器该值是其参数中指定的类型,如果在运行时期间调用此方法的值与您在type参数中指定的值不匹配,则会抛出异常。 Ie in a.asInstanceOf[B] the provided value a must be of a type B or inherit from it - otherwise you'll get an exception. a.asInstanceOf[B]所提供的价值a必须是一个类型的B或继承它-否则,你会得到一个例外。

Just done more tests(compiled and run), I think this may be from one bug of asInstanceOf, it won't do cast. 刚做了更多的测试(编译和运行),我想这可能是来自asInstanceOf的一个bug,它不会进行强制转换。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM