加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala中的classOf、isInstanceOf、asInstanceOf

发布时间:2020-12-16 09:46:29 所属栏目:安全 来源:网络整理
导读:scala中的classOf、isInstanceOf、asInstanceOf Scala的三个预定义(predefined)方法,我们经常用到。 object PredefineTest { def main(args: Array[String]): Unit = { val c : Char = 97. asInstanceOf[Char] "hello" .asInstanceOf[String] 1. asInstance

scala中的classOf、isInstanceOf、asInstanceOf

Scala的三个预定义(predefined)方法,我们经常用到。

object PredefineTest{  
  def main(args: Array[String]): Unit = {  
    val c : Char = 97.asInstanceOf[Char]  
    "hello".asInstanceOf[String]  
    1.asInstanceOf[Long]  
    val it: Seq[String] = List("a","b")  
    it.asInstanceOf[List[String]]  

    "hello".isInstanceOf[String]  

    classOf[String]  
    /* val c : Char = 97.asInstanceOf[Char] println("hello".asInstanceOf[String]) println(1.asInstanceOf[Long]) val it: Seq[String] = List("a","b") println(it.asInstanceOf[List[String]]) println("hello".isInstanceOf[String]) println(classOf[String]) hello 1 List(a,b) true class java.lang.String */
  }  
}

使用scalac -Xprint:cleanup PredefineTest.scala,Scala编译器输出的main方法体内代码的抽象语法树(AST)信息如下:

val c: Char = 97.toChar();  
("hello": java.lang.String);  
1.toLong();  
val it: Seq = immutable.this.List.apply(scala.this.Predef.wrapRefArray(Array[java.lang.String]{"a","b"}.$asInstanceOf[Array[java.lang.Object]]()));  
it.$asInstanceOf[List]();  
"hello".$isInstanceOf[java.lang.String]();  
{  
  classOf[java.lang.String];  
  ()  
}

使用jd反编译工具查看对应代码如下:

char c = (char)97;  
"hello";  
1;  
Seq it = List..MODULE$.apply(Predef..MODULE$.wrapRefArray((Object[])new String[] { "a","b" }));  
((List)it);  

("hello" instanceof String);  
String.class;

classOf[T]

获取类型T的Class对象。

classOf方法定义在scala.Predef object:

object Predef extends LowPriorityImplicits {  
      /** Return the runtime representation of a class type. This is a stub method. * The actual implementation is filled in by the compiler. */  
      def classOf[T]: Class[T] = null  
    ...  
}

classOf的注释翻译过来的意思是:返回在运行过程中的类型。这是一个存根方法。具体的实现是由编译器填补(自动生成)。

Predef object是默认导入的,所以classOf方法相当于一个全局方法。

isInstanceOf[T]

判断对象是否为T类型的实例。

isInstanceOfasInstanceOf由scala.Any类定义,所以所有对象都自动拥有isInstanceOf和asInstanceOf这两个方法。

再看一下例子:

scala> 1.isInstanceOf[String]  
res0: false  

scala> List(1).isInstanceOf[List[String]]  
res0: true

由于Scala像Java一样泛型存在类型擦除的原因,List(1).isInstanceOf[List[String]]及相当于List(1).isInstanceOf[List[_]],List(1)是List的实例。这样的问题在模式匹配的时候也会遇到,关于如何克服类似的问题,可以参见scala中的类型擦除的问题

asInstanceOf[T]

将对象类型强制转换为T类型。

还是由于泛型存在类型擦除的原因,1.asInstanceOf[String]在运行时会抛出ClassCastException异常,而List(1).asInstanceOf[List[String]]将不会。

在scala 讨论组里有人问道这样一个问题:

“I expect "new AnyRef().isInstanceOf[AnyVal]" to be false,but I get true instead”
scala> new AnyRef().isInstanceOf[AnyVal]
res0: Boolean = true

大家有兴趣看以看看后面的解答,不过试了scala 2.9,这种用法已经被编译器禁止了:

scala> new AnyRef().isInstanceOf[AnyVal]
<console>:8: error: type AnyVal cannot be used in a type pattern or isInstanceOf test
new AnyRef().isInstanceOf[AnyVal]

还有,值得提一下的一个小细节就是,通过观察编译输出的AST,知道对于在基本类型如Int等的对象上调用asInstanceOf[T],Scala会将其转换为调用相应的toT方法,如 97.asInstanceOf[Char],就会转换为97.toChar,其中toChar定义在scala.Int:

final class Int extends AnyVal {  
  ...  
  def toChar: Char = sys.error("stub")  
  ...  
}

而后, Scala编译器会进一步将其编译成与“(char)97”相同的字节码。

结论

总而言之,我们把classOf[T]看成Java里的T.class,obj.isInstanceOf[T]看成 obj instanceof T,obj.asInstanceOf[T]看成(T)obj就对了。

但是同样也要注意类型擦除造成的问题。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读