scala雾中风景(11): isInstanceOf与类型擦拭

scala中用isInstanceOf判断一个对象实例是否是某种类型时,如果类型包含参数类型,会被擦拭掉(jvm的做法)。所以会导致例如下面的问题:

scala> (1,2).isInstanceOf[Tuple2[String,String]]

<console>:11: 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]]
                            ^
res33: Boolean = true

在给出了一段警告之后,结果返回true,如果数据对象支持模式匹配且元素较少,可以用模式匹配来精确判断:

scala> (1,2) match{ case(_:Int, _:Int) => println("ok"); case _ => "no"}
ok

但元素比较多的话,或数据不支持模式匹配,要判断参数类型,就需要让编译器在运行时保持参数类型的信息了,在scala里是通过TypeTag来实现的,参考scala类型系统:19) Manifest与TypeTag

scala> def checkType[A: TypeTag](a: A, t: Type) =  typeOf[A] <:< t

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

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

scala雾中风景(11): isInstanceOf与类型擦拭》上有5条评论

  1. jianjia

    最近在拜读您的博客,这里有个问题请教下,def checkType[A: TypeTag](a: A, t: Type) = typeOf[A] <:< t 这个函数我在交互界面上可以定义并调用,但是在IDEA中定义时却报 Error:(29, 49) not found: value typeOf。。。这错误,我在代码中已经import scala.reflect._。不知道为何,请指教,多谢!

    回复
    1. hongjiang 文章作者

      typeOf是runtime包对象里的universe实例里的方法,要这样引入:import scala.reflect.runtime.universe._

      回复
  2. jianjia

    解决了,我用的gradle构建项目,添加了 ‘scala’插件,但是IDEA好像没把scala-reflect引进来,显式地添加该依赖就可以了。多谢!

    回复
  3. snow

    scala> def tt(msg:(Any,Any))=msg match{case (_:Int,_:Int)=>println(“ok”);c
    >”wrong”}
    tt: (msg: (Any, Any))Any

    scala> tt((1,2))
    ok
    res123: Any = ()

    scala> tt((1,”b”))
    res124: Any = wrong

    回复
    1. snow

      def tt(msg:(Any,Any))=msg match{case (_:Int,_:Int)=>println(“ok”);case _=>”wrong”}
      少复制了点,看您这里的内容:http://hongjiang.info/scala-pitfalls-13/

      回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注