scala object 转Class Scala强制类型转换

 

asInstanceOf[T]

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

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

package resti.web
 
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.RequestMapping
import resti.domain.HttpApi
import resti.service.HttpApiRepository
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.web.bind.annotation.RequestMethod
 
@Controller
@RequestMapping(Array("/product"))
class ProductController @Autowired() (private val httpApiRepository: HttpApiRepository) {
 
  @RequestMapping(method = Array(RequestMethod.GET))
  def list(model: Model) = {
    // get current user
    val userDetails = SecurityContextHolder.getContext().getAuthentication().getPrincipal().asInstanceOf[UserDetails]
    model.addAttribute("currentUser", userDetails.getUsername)
    
    model.addAttribute("products", httpApiRepository.findProducts())
    "product/list"
  }
 

}

classOf、isInstanceOf、asInstanceOf三个预定义方法分析

Scala的三个预定义(predefined)方法,我们经常用到;它们用来感觉很简单, 但是里面还是隐藏了一些细节东西,不妨花点时间来分析分析。

先上代码

PredefineTest.scala

Scala代码  
  1. object PredefineTest{
  2. def main(args: Array[String]):Unit = {
  3. val c : Char = 97.asInstanceOf[Char]
  4. "hello".asInstanceOf[String]
  5. 1.asInstanceOf[Long]
  6. val it: Seq[String] = List("a", "b")
  7. it.asInstanceOf[List[String]]
  8. "hello".isInstanceOf[String]
  9. classOf[String]
  10. }
  11. }

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

Scala代码  
  1. val c: Char = 97.toChar();
  2. ("hello": java.lang.String);
  3. 1.toLong();
  4. val it: Seq = immutable.this.List.apply(scala.this.Predef.wrapRefArray(Array[java.lang.String]{"a", "b"}.$asInstanceOf[Array[java.lang.Object]]()));
  5. it.$asInstanceOf[List]();
  6. "hello".$isInstanceOf[java.lang.String]();
  7. {
  8. classOf[java.lang.String];
  9. ()
  10. }

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

Java代码  
  1. char c = (char)97;
  2. "hello";
  3. 1;
  4. Seq it = List..MODULE$.apply(Predef..MODULE$.wrapRefArray((Object[])new String[] { "a", "b" }));
  5. ((List)it);
  6. ("hello" instanceof String);
  7. String.class;

结合上面源码来进行分析

classOf[T]

获取类型T的Class对象

classOf方法定义在scala.Predef object:

Scala代码  
  1. object Predef extends LowPriorityImplicits {
  2. def classOf[T]: Class[T] = null
  3. ...

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. scala> 1.isInstanceOf[String]
  2. res0: false
  3. scala> List(1).isInstanceOf[List[String]]
  4. 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 讨论组里有人问道这样一个问题

”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方法, 如 1.asInstanceOf[Char], 就会转换为 97.toChar, 其中toChar 定义在 scala.Int:

Scala代码  
  1. final class Int extends AnyVal {
  2. ...
  3. def toChar: Char = sys.error("stub")
  4. ...
  5. }

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

结论

总而言之,我们把classOf[T]看成Java里的T.class, obj.isInstanceOf[T]看成 obj instanceof T, obj.asInstanceOf[T]看成(T)obj就对了。scala为我们提供了语法糖,但也免不了类型擦除问题的影响。

值得探讨的地方

个人感觉,Scala对Java的类这一块没什么增强, 比如像Ruby一样类文字量也是对象(虽然理解起来有点绕,但是更能体现面向对象一致性),就不用classOf[T]这样添足的写法,而是:object.getClass == String 。如此,是不是JVM的限制,还是Scala目前的关注点不在此?

原文地址:http://blog.sina.com.cn/s/blog_7d553bb50102wa7h.html

scala object 转Class Scala强制 类型转换的更多相关文章

  1. scala学习手记35 - 隐式类型转换

    先来看一下下面的内容: 2 days "ago" 5 days "from_now" 如上的内容具体应该是什么呢?不过怎么看也不像是代码.不过既然是在学代码,拿 ...

  2. Beginning Scala study note(3) Object Orientation in Scala

    1. The three principles of OOP are encapsulation(封装性), inheritance(继承性) and polymorphism(多态性). examp ...

  3. 集合框架的类和接口均在java.util包中。 任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换。

    集合框架的类和接口均在java.util包中. 任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换.

  4. Scala进阶之路-Scala高级语法之隐式(implicit)详解

    Scala进阶之路-Scala高级语法之隐式(implicit)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一 ...

  5. 《Scala程序设计》暨Scala简介

    JVM语言 JVM上的语言越来越多了,从前几年的groovy.Scala和Clojure,现在又听说一门Kotlin.对于前三种语言,groovy算是JVM平台上的动态脚本语言,可以类比Python: ...

  6. Beginning Scala study note(9) Scala and Java Interoperability

    1. Translating Java Classes to Scala Classes Example 1: # a class declaration in Java public class B ...

  7. Beginning Scala study note(8) Scala Type System

    1. Unified Type System Scala has a unified type system, enclosed by the type Any at the top of the h ...

  8. Beginning Scala study note(6) Scala Collections

    Scala's object-oriented collections support mutable and immutable type hierarchies. Also support fun ...

  9. JavaScript学习10 JS数据类型、强制类型转换和对象属性

    JavaScript学习10 JS数据类型.强制类型转换和对象属性 JavaScript数据类型 JavaScript中有五种原始数据类型:Undefined.Null.Boolean.Number以 ...

随机推荐

  1. 整合 Ext JS 和第三方类库

    介绍 ExtJS提供了许多高度可定制化内置组件.如果它不在框架(framework)里面,你可以很容易的扩展这些类,或者浏览Sencha市场(Sencha Market) 寻找你可能需要的任何东西.那 ...

  2. 洛谷 P1347 排序

    题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B ...

  3. JSON与XML的区别比较(转)

    原文链接:JSON与XML的区别比较 1.定义介绍 (1).XML定义扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以 ...

  4. Swift:宏定义

    一.简述 swift中并没有加入宏系统,C语言使用#define定义的基本常量在导入Swift时被Swift编译自动转为Swfit语言的全局变量.但复杂的宏定义不能被Swift转换.Swift中类似宏 ...

  5. 一次问题追查----短字符串签名算法引发的bug

    近期开发代码, 出现了一些诡异现象.追查原因是公司使用的签名函数出现的问题. 问题: 代码使用的签名库函数, 对于<=4字节的字符串, 签名就是本身. #include<stdio.h&g ...

  6. javaScript:让文本框内的最后一个文字的后面获得焦点

    //当失去交点以后 让文本框内的文字获得焦点 并且光标移到最后一个字后面 function myfocus(myid) { if(isNav){ document.getElementById(myi ...

  7. 转:PCA的Python实现

    http://blog.csdn.net/jerr__y/article/details/53188573 本文主要参考下面的文章,文中的代码基本是把第二篇文章的代码手写实现了一下. - pca讲解: ...

  8. CNN-卷积层和池化层学习

    卷积神经网络(CNN)由输入层.卷积层.激活函数.池化层.全连接层组成,即INPUT-CONV-RELU-POOL-FC (1)卷积层:用它来进行特征提取,如下: 输入图像是32*32*3,3是它的深 ...

  9. 【图片识别】Java中使用tess4J进行图片文字识别(支持中文)(转)

    http://blog.csdn.net/wsk1103/article/details/54173282 java中识别文字比较简单,使用的软件是tesseractocr(使用的版本是3.02,3以 ...

  10. Spark:求出分组内的TopN

    制作测试数据源: c1 85 c2 77 c3 88 c1 22 c1 66 c3 95 c3 54 c2 91 c2 66 c1 54 c1 65 c2 41 c4 65 spark scala实现 ...