1. 程式人生 > >isInstanceOf與型別擦除

isInstanceOf與型別擦除

轉載自:http://hongjiang.info/scala-pitfalls-11-type-erasure/

       scala中用isInstanceOf判斷一個物件例項是否是某種型別時,如果型別包含引數型別,會被擦除(jvm的做法)。所以會導致例如下面的問題:
scala> (1,2).isInstanceOf[Tuple2[String,String]]
<console>:14: warning: fruitless type test: a value of type (Int, Int) cannot also be a (String, String) (but still might match its erasure)
       (1,2).isInstanceOf[Tuple2[String,String]]
                         ^
res11: Boolean = true
       在給出了一段警告之後,結果返回true,如果資料物件支援模式匹配且元素較少,可以用模式匹配來精確判斷:
scala> (1,2) match{ case(_:Int, _:Int) => println("ok"); case _ => "no"}
ok
res12: Any = ()
       但元素比較多的話,或資料不支援模式匹配,要判斷引數型別,就需要讓編譯器在執行時保持引數型別的資訊了,在scala裡是通過TypeTag來實現的,TypeTag知識點參考http://hongjiang.info/scala-type-system-manifest-vs-typetag/。如下方式可以作型別檢查:
scala>  def checkType[A: TypeTag](a: A, t: Type) =  typeOf[A] <:< t
checkType: [A](a: A, t: reflect.runtime.universe.Type)(implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean

scala> checkType((1,2), typeOf[Tuple2[String,String]])
res13: Boolean = false

scala>  checkType((1,2), typeOf[Tuple2[Int,Int]])
res14: Boolean = true