Вопрос по scala – как правильно использовать asInstanceOf в Scala

12

Я играл с основными типами данных 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) приведение от любого типа к 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

В этом случае предполагается, что код создает исключение ClasscastException, но это не так. Это мое беспокойство.

In the third case, I get a 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. Я знаю, что этот пример никоим образом не является примером из реального мира, но я пытался обернуть голову вокруг основ.

Ваш Ответ

3   ответа
14

double вint (в случае Scala,Double вInt). С другой стороны, вы не можете разыгратьjava.lang.Double вjava.lang.Int.

Когда вы объявляетеDouble какAnyВы явно просите компилятор забыть, что вы дали емуDouble, Поэтому для поддержкиAny Интерфейс, компилятор хранит значение в виде двойного блока (т.е.java.lang.Double).

Поведение кажется запутанным, но это не ошибка. Согласно & # xA7; 12.1Scala Language Spec:

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

0

я думаю, что это может быть из-за одной ошибки asInstanceOf, он не будет кастовать.

Последняя строка команды дает мне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
8

преобразовать & quot ;.

Стандартные методы конвертации начинаются сtoнапример,20d.toInt преобразует значение20 типаDouble значение 20 типаInt.

asInstanceOf с другой стороны, это специальный метод приведения типов. Все, что он делает, сообщает компилятору, что значение имеет тип, указанный в его параметре, если во время выполнения значение, для которого вы вызываете этот метод, не совпадает с тем, которое вы указали в параметре типа, вы получите исключение. То есть вa.asInstanceOf[B] предоставленная стоимостьa должен быть типаB или наследовать от него - в противном случае вы получите исключение.

Извините за этот незаконченный комментарий. Я хотел сказать, что в моей программе код - val int = double.asInstanceOf [Int] - не генерирует исключение, как должно. Имеет смысл, потому что, как вы правильно сказали, мы не можем привести Double к Int, потому что это разные типы. Поэтому я обеспокоен тем, почему я НЕ получаю исключение ilango
@ilangogurusamy Хм .. Я тоже это воспроизвел. Странное поведение. Я подозреваю, что это может быть из-за закулисной магии бокса-распаковки, происходящей с примитивами.
Как вы думаете, это пахнет ошибкой? ilango

Похожие вопросы