scala中ClassOf、asInstenceOf、isInstanceOf三个预定义方法分析
classOf、isInstanceOf、asInstanceOf三个预定义方法分析
Scala的三个预定义(predefined)方法,我们经常用到;它们用来感觉很简单, 但是里面还是隐藏了一些细节东西,不妨花点时间来分析分析。
先上代码
PredefineTest.scala
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]
}
}
使用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类型的实例。
isInstanceOf和asInstanceOf 由scala.Any类定义,Scala类层级的根类;其中class scala.AnyRef 继承自Any,是所有引用类型的基类;trait scala.AnyVal 也继承自Any,是所有基本类型的实现的trait。所以所有对象都自动拥有isInstanceOf和asInstanceOf这两个方法。
特别注意的是 Any 和AnyRef 这两个类属于“编译时类型”(虚拟类型?),不存在于运行时。所以这两者在Scala中都未提供源码,其语义由编译器在编译时构建。
再看一下例子:
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的实例.
asInstanceOf[T]
将对象类型强制转换为T类型。
还是由于泛型存在类型擦除的原因,1.asInstanceOf[String]在运行时会抛出ClassCastException异常,而List(1).asInstanceOf[List[String]]将不会。
在scala 讨论组里有人问道这样一个问题:
scala> new AnyRef().isInstanceOf[AnyVal]
res0: Boolean = true
大家有兴趣看以看看后面的解答,不过试了scala 2.9, 这种用法 已经被编译器禁止了:
<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方法, 如 1.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就对了。scala为我们提供了语法糖,但也免不了类型擦除问题的影响。
本文来自:http://www.myexception.cn/program/855572.html
scala中ClassOf、asInstenceOf、isInstanceOf三个预定义方法分析的更多相关文章
- Java8学习笔记(二)--三个预定义函数接口
三个函数接口概述 JDK预定义了很多函数接口以避免用户重复定义.最典型的是Function: @FunctionalInterface public interface Function<T, ...
- openerp经典收藏 对象的预定义方法(转载)
对象的预定义方法 原文:http://shine-it.net/index.php/topic,2159.15.html 每个OpenERP的对象都有一些预定义方法,这些方法定义在基类osv.osv中 ...
- C#中获取当前系统中安装的所有字体及预定义颜色
需要引用命名空间using System.Drawing.Text;.... //获取系统字体:InstalledFontCollection fc = new InstalledFontCollec ...
- (三)使用预定义模型QDirModel的例子
使用预定义模型QDirModel的例子 Main.cpp #include <QApplication> #include "directoryviewer.h" in ...
- scala中停止循环的三种方式
1:使用return关键字 object BreakLoop { //1.使用return关键字 def add():Unit= { for(i <- 1 to 10){ if(i==7){ / ...
- talib 中文文档(三):talib 方法大全
Function API Examples Similar to TA-Lib, the function interface provides a lightweight wrapper of th ...
- scala中常用但其他语言不常见的符号含义
本文旨在介绍Scala在其他语言中不太常见的符号含义,帮助理解Scala Code. 随着我对Scala学习的深入,我会不断增加该篇博文的内容. 修改记录 ----2016.11.23 新增scal ...
- Scala中的类学习
Scala中的类学习 从java了解类的情况下,了解Scala的类并不难.Scala类中的字段自动带getter和setter方法,用@BeanProperty注解生成javaBean对象的getXX ...
- 第2节 Scala中面向对象编程:1、类的定义;2、类的构造器;3、object和伴生对象;4、apply和main方法
6. 类.对象.继承.特质 Scala的类与Java.C++的类比起来更简洁,学完之后你会更爱Scala!!! 6.1. 类 6.1.1. 类的定义 package cn.itcast ...
随机推荐
- 跨平台(win和unix)的线程封装类
#ifdef WIN32 #include <Windows.h> #include <process.h> #else #include <pthread.h> ...
- 免费下载 SetupVPN CRX 3.7.0 for Chrome OR QQ浏览器
免费下载 SetupVPN CRX 3.7.0 for Chrome OR QQ浏览器 Lifetime Free VPN(微劈嗯) 下载setupvpn 3.7.0的crx文件, 打开chrome的 ...
- 002-jdk-数据结构-工具类Collections、Arrays、System.arraycopy
常用备注 一.LIst to Array List<String> list = new ArrayList<String>(); Object[] array=list.to ...
- jackson将json数组转成List、普通数组。
package com.mkyong; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jacks ...
- node.js运行内存堆溢出的解决办法
我是在将一组80多列13万多行的数据通过node-xlsx的时候出现的内存堆溢出的情况. 解决办法时将: node app.js 改成: node --max_old_space_size=10000 ...
- DELL服务器管理工具和RACADM介绍
DELL服务器管理工具和RACADM介绍 一.Dell服务器管理工具介绍 Dell对服务器(DELL PowerEdge)的管理主要提供了三种管理工具,分别是Dell Remote Access Co ...
- 事理学神器PDCA
做事情都按PDCA循环来做,基本就是一个靠谱的人. 这个方法论其实也符合架构师的思维中的分治理论.把大事拆分成一件件小事,并把小事做好. Plan Do Check Action
- 告诉你:DOS系统实例手册系列专辑连载中
DOS系统实例手册系列专辑连载中 内容提要:
- js唤醒手机APP
if (navigator.userAgent.match(/android/i)) { // 通过iframe的方式试图打开APP,如果能正常打开,会直接切换到APP,并自动阻止a标签的默认行为 / ...
- linux下如何查看一个服务所在的安装路径?
当接手一个不是自己维护的linux服务器,我们常常会想要看看该服务器上是否安装了某个服务,这个服务安装的路径在哪? redis 是开发过程中常常会用到的一个服务,我这里就以这个服务为例,进行说明. 1 ...