Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use asInstanceOf properly in Scala

Tags:

scala

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 stackoverflow for other questions on this topic and I came up with this With this information in hand, I wrote up a silly program.

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

  2. In the second case, I get the following result: int is 123 x is 123 Int x is 123

In this case, the code is supposed to produce a ClasscastException, but it does not. That is my worry.

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

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.

like image 816
ilango Avatar asked Sep 10 '12 19:09

ilango


People also ask

What is asInstanceOf in Scala?

asInstanceOf [ Recognizer ] This Scala code is equivalent to the following Java code: Recognizer recognizer = ( Recognizer ) cm . lookup ( "recognizer" ); The asInstanceOf method is defined in the Scala Any class and is therefore available on all objects.

What is asInstanceOf?

asInstanceOf[Bar] is a type cast, which is primarily a runtime operation. It says that the compiler should be coerced into believing that foo is a Bar . This may result in an error (a ClassCastException ) if and when foo is evaluated to be something other than a Bar at runtime.


2 Answers

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.

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

The behavior does seem confusing, but it's not a bug. According §12.1 of the Scala 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).

like image 81
Aaron Novstrup Avatar answered Sep 30 '22 07:09

Aaron Novstrup


I think you've confused the terms "cast" and "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.

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.

like image 23
Nikita Volkov Avatar answered Sep 30 '22 07:09

Nikita Volkov