类和类型

List<String>和List<Int>类型是不一样的,但是jvm运行时会采用泛型擦除。导致List<String>和List<Int>都是Class<List>.为了得到正确的类型,需要通过反射。

泛型擦除

Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。泛型擦除是为了兼容jdk1.5之前的jvm,在这之前是不支持泛型的。

classOf与getClass方法的差异

scala> class  A
scala> val a = new A scala> a.getClass
res2: Class[_ <: A] = class A scala> classOf[A]
res3: Class[A] = class A

上面显示了两者的不同,getClass 方法得到的是 Class[A]的某个子类,而 classOf[A] 得到是正确的 Class[A],但是去比较的话,这两个类型是equals为true的

classOf和getClass

classOf获取运行时的类型。classOf[T] 相当于 java中的T.class

  val listClass = classOf[List[_]]
* // listClass is java.lang.Class[List[_]] = class scala.collection.immutable.List
val mapIntString = classOf[Map[Int,String]]
* // mapIntString is java.lang.Class[Map[Int,String]] = interface scala.collection.immutable.Map
* }}}

而getClass:

scala> class  A
scala> val a = new A scala> a.getClass
res2: Class[_ <: A] = class A scala> classOf[A]
res3: Class[A] = class A

上面显示了两者的不同,getClass 方法得到的是 Class[A]的某个子类,而 classOf[A] 得到是正确的 Class[A],但是去比较的话,这两个类型是equals为true的

scala> a.getClass  == classOf[A]
res13: Boolean = true

这种细微的差别,体现在类型赋值时,因为java里的 Class[T]是不支持协变的,所以无法把一个 Class[_ < : A] 赋值给一个 Class[A]

scala> val c:Class[A] = a.getClass
<console>:: error: type mismatch;

类(class)与类型(type)是两个不一样的概念
(在java里因为早期一直使用class表达type,并且现在也延续这样的习惯);类型(type)比类(class)更”具体”,任何数据都有类型。类是面向对象系统里对同一类数据的抽象,在没有泛型之前,类型系统不存在高阶概念,直接与类一一映射,而泛型出现之后,就不在一一映射了。比如定义class List[T] {}, 可以有List[Int] 和 List[String]等具体类型,它们的类是同一个List,但类型则根据不同的构造参数类型而不同。

类型一致的对象它们的类也是一致的,反过来,类一致的,其类型不一定一致。

scala> classOf[List[Int]] == classOf[List[String]]
res16: Boolean = true scala> typeOf[List[Int]] == typeOf[List[String]]
res17: Boolean = false

ClassTag

ClassTag[T]保存了被泛型擦除后的原始类型T,提供给运行时的。

scala> def mkArray[T : ClassTag](elems: T*) = Array[T](elems: _*)
mkArray: [T](elems: T*)(implicit evidence$: scala.reflect.ClassTag[T])Array[T]

TypeTag

TypeTag则保存所有具体的类型

import scala.reflect.runtime.universe._
def paramInfo[T](x: T)(implicit tag: TypeTag[T]): Unit = {
val targs = tag.tpe match { case TypeRef(_, _, args) => args }
println(s"type of $x has type arguments $targs")
}
scala> paramInfo()
type of has type arguments List()
scala> paramInfo(List(, ))
type of List(, ) has type arguments List(Int)

可以看到,获取到的类型是具体的类型,而不是被擦除后的类型List(Any)

Scala的类与类型的更多相关文章

  1. 泛函编程(4)-深入Scala函数类

    既然是泛函编程,多了解一下函数自然是免不了的了: 方法(Method)不等于函数(Function) 方法不是函数但可以转化成函数:可以手工转换或者由编译器(compiler)在适当的情况下自动转换. ...

  2. scala学习-类与对象

    类 / 对象 [<快学Scala>笔记] 一.类 1.Scala中的类是公有可见性的,且多个类可以包含在同一个源文件中: class Counter{ private var value ...

  3. Scala函数---既存类型

    语法: Type ::= InfixType ExistentialClauses ExistentialClauses ::= „forSome‟ „{‟ ExistentialDcl {semi ...

  4. Programming In Scala笔记-第十七章、Scala中的集合类型

    本章主要介绍Scala中的集合类型,主要包括:Array, ListBuffer, Arraybuffer, Set, Map和Tuple. 一.序列 序列类型的对象中包含多个按顺序排列好的元素,可以 ...

  5. Scala:类,对象和特征(接口)

    http://blog.csdn.net/pipisorry/article/details/52902609 Scala类和对象 类是对象的抽象,而对象是类的具体实例.类是抽象的,不占用内存,而对象 ...

  6. Scala的类层级讲解

    Scala的类层级 Scala里,每个类都继承自通用的名为Any的超类. 因为所有的类都是Any的子类,所以定义在Any中的方法就是"共同的"方法:它们可以被任何对象调用. Sca ...

  7. Scala进阶之路-Scala中的高级类型

    Scala进阶之路-Scala中的高级类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类型(Type)与类(Class)的区别 在Java里,一直到jdk1.5之前,我们说 ...

  8. Scala学习之路 (六)Scala的类、对象、继承、特质

    一.类 1.类的定义 scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用 ...

  9. Scala进阶之路-Scala特征类与unapply反向抽取

    Scala进阶之路-Scala特征类与unapply反向抽取 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Scala特征类分析 1>.Unit 答:用于定义返回值类型, ...

随机推荐

  1. 帝国CMS 列表模板list.var支持程序代码

    1.增加模板时list.var模板需要勾选“使用程序代码”选项.如图: 2.直接添加PHP代码,不需要加<?和?>程序开始和结束标记. 3.字段值数组变量为$r,对应的字段变量为$r[字段 ...

  2. NodeJs生成SVG图形验证码

    背景:短信接口有调用限制,如果受到恶意攻击,很容易就爆掉,所以需要一系列验证机制,后端采用签名加密的方式,而前端要做人机识别,有两个要求: 1)不能使用文本式的验证码,很简单就能拿到 2)所有验证逻辑 ...

  3. go-study

    package (包) 一个目录下面所有的.go文件的包名必须相同. 包名一般和目录名相同(是约定, 不是强制), 包名都小写 main包是一个特殊的包名, 在main包中, 必须包含func mai ...

  4. 关于截取字符串substr和substring两者的区别

    https://blog.csdn.net/adley_function/article/details/52130762 substr和substring两个都是截取字符串的. 两者有相同点,如果只 ...

  5. BaiduMap 鼠标绘制矩形选框四个顶角坐标的获取

    雪影工作室版权全部.转载请注明[http://blog.csdn.net/lina791211] 1.博文产生原因 在使用百度Map开放API进行开发的时候,遇到了一个需求,非常easy的一个需求. ...

  6. JavaScript------字符串与HTML格式相互转换

    转载: http://blog.sina.com.cn/s/blog_4cb0b0fc0100aoo1.html 代码:: 1.将字符转换成Html function encodeHtml(str){ ...

  7. pow()

    pow() 如果接收两个参数,如 pow(x, y),则结果相当于 x**y,也就是 x 的 y 次方pow() 如果接收三个参数,如 pow(x, y, z),则结果相当于 (x**y) % z,也 ...

  8. IOS中数组的使用(NSArray, NSSet, NSDictionary)

    一.Foundation framework中用于收集cocoa对象(NSObject对象)的三种集合分别是: NSArray 用于对象有序集合(数组)NSSet 用于对象无序集合(集合) NSDic ...

  9. c++11实现optional

    optional< T> c++14中将包含一个std::optional类,optional< T>内部存储空间可能存储了T类型的值也可能没有存储T类型的值.当optiona ...

  10. MQTT的学习研究(五) MQTT moquette 的 Blocking API 发布消息服务端使用

    参看官方文档: http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/index.jsp?topic=/com.ibm.mq.amqtat.doc/t ...