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. 2 番目のケースでは、次の結果が得られます: int is 123 x is 123 Int x is 123

この場合、コードは ClasscastException を生成するはずですが、生成しません。それが私の心配です。

  1. 3 番目のケースでは、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) では、プリミティブdoubleint(Scala の場合はDouble)にキャストできますInt。一方、 にキャストjava.lang.Doubleすることはできませんjava.lang.Int

Doubleをとして宣言すると、Any明示的にコンパイラにDouble. したがって、Anyインターフェイスをサポートするために、コンパイラは値をボックス化された double (つまり、java.lang.Double) として格納しています。

この動作は紛らわしいように見えますが、バグではありません。Scala言語仕様の§12.1によると:

T が数値型の場合、テスト x.asInstanceOf[T] は特別に扱われます (§12.2)。この場合、キャストは変換メソッド x.toT (§12.2.1) のアプリケーションに変換されます。

于 2012-09-10T21:32:52.627 に答える
13

「キャスト」と「変換」という用語を混同していると思います。

標準の変換メソッドは で始まりますto。たとえば、型の値を型の値 20 に20d.toInt変換します。20DoubleInt

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 に答える