scala的反射

??如果当初Scala没有选择基于Jvm,那么Scala是否还能取得今天的成就吗?Jvm为Scala带了稳健强大的性能,同时也无法避免类型擦除的约束。

??作为Jvm上的先进语言,Scala在生成字节码时,编译器附加了额外的类型信息,及时class的泛型参数被擦除了,scala仍然可以获取泛型信息。

主要存在三种api:

  • TypeTag,可获取一个类型的全部信息,包括高阶类型,比如List[List[List[String]]]类型。
  • ClassTag,可获取类型的部分信息。ClassTag[List[List[String]]],仅可得到类型擦除后的类的类型,也就是scala.collection.immutable.List
  • WeakTypeTag是可以用于获取抽象类型,比如def foo[A]=List.empty[A],想要获取这个抽象类型A,需要使用WeakTypeTag
? scala
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_141).
Type in expressions for evaluation. Or try :help.

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> val tt=typeTag[List[List[String]]]
tt: reflect.runtime.universe.TypeTag[List[List[String]]] = TypeTag[scala.List[scala.List[String]]]

scala> import scala.reflect._
import scala.reflect._

scala> val ct=classTag[Map[String,Int]]
ct: scala.reflect.ClassTag[Map[String,Int]] = scala.collection.immutable.Map

scala> ct.runtimeClass
res1: Class[_] = interface scala.collection.immutable.Map

利用编译器获取类型信息

??之前说过,scala编译器在编译器全部保存了相关的类型信息,仅仅需要借助隐式参数由编译器传入即可。

import scala.reflect.runtime.universe._

def typeInfo[T](x: T)(implicit tag: TypeTag[T]) = tag.tpe match {
    case TypeRef(preType: Type, symbol: Symbol, typeParams: List[Type]) =>
      println(s"preType.typeSymbol : ${preType.typeSymbol}")
      println(s"preType : ${preType}")
      println(symbol.fullName)
      println(typeParams)
  }

typeInfo(Map("1"->1))
//打印如下::
preType.typeSymbol : package immutable
preType : scala.collection.immutable.type
scala.collection.immutable.Map
List(java.lang.String, Int)

在以上程序中,preType是x对象的前缀路径的类型,这里的scala.collection.immutable是一个package。symbol就是参数x的符号信息,typeParams是x对应的类型的类型参数,对于Map[String,Int],那么其类型参数有java.lang.StringInt

??一句话解释scala的反射机制:编译时期额外类型信息,此类型信息可以用编码显式给出,也可以用编译器推断。以下的例子可以说明:

def getType[T](x: T)(implicit tag: TypeTag[T]): Type = tag.tpe

??现有一个函数getType(x),可以此获取某个对象x的类型信息。显式给出类型为Any,编译器则传入隐式tag:TypeTag[Any]对象。

println(getType[Any](List(1, 2, 3)))
//打印 Type[Any]
println(getType(List(1, 2, 3)))
//打印 Type[List[Int]]

Type之间的比较操作

??type之间的比较主要有三种类型:

  • 比较两个类型是否是继承关系
  • 判断两个类型之间的相等性
  • 给定某一确定的类型的成员方法或者属性

??现在有两个trait,分别是AB,且AB的父级。

trait A
trait B extends A
val aType = typeOf[A]
val bType = typeOf[B]
println(aType =:= bType) //false
println(aType <:< bType) //false
println(bType <:< aType) //true
println(aType <:< aType) //true

??对于给定的两个Type实例,<:<方法可以用于比较两个类型是否具有父子类型关系,作用与Java中的isInstance类似。

??当使用==比较两个类型时,类型别名与实际类型被认为是不同类型,而=:=会用最根本的类型去比较。

type PersonName=String
val t1= typeOf[PersonName]
val t2= typeOf[String]
t1 == t2 //false
t1 =:= t2 //true

??TypeTag可以等效的看作为scala2.10版本以前的ManifestClassTag也可以等效的看作为scala2.10版本之前的ClassManifest

原文地址:https://www.cnblogs.com/hangscer/p/8463495.html

时间: 2024-10-10 23:21:33

scala的反射的相关文章

Scala Types 1

在 Scala 中所有值都有一种对应的类型 单例类型 形式:value.type,返回类型 value / null 场景1:链式API调用时的类型指定 class Super { def m1(t: Int) = {println(t); this} def m2(t: Int) = {println(t); this} } // 正常打印 new Super().m1(1).m2(2) class Child extends Super { def c1(t: Int) = {println

sparkSQL实战详解

摘要   如果要想真正的掌握sparkSQL编程,首先要对sparkSQL的整体框架以及sparkSQL到底能帮助我们解决什么问题有一个整体的认识,然后就是对各个层级关系有一个清晰的认识后,才能真正的掌握它,对于sparkSQL整体框架这一块,在前一个博客已经进行过了一些介绍,如果对这块还有疑问可以看我前一个博客:http://9269309.blog.51cto.com/9259309/1845525.本篇博客主要是对sparkSQL实战进行讲解和总结,而不是对sparkSQL源码的讲解,如果

Scala反射

最近想用scala写一个分布式爬虫框架.没有反射就没有框架.所以需要准备下scala反射的知识 什么是反射? 反射是程序的一种自省能力.利用反射可以从更高的抽象等级写程序甚至在运行时改变程序本身 反射有哪些类型? 根据使用的时机不同,可以分为:运行时反射,编译时反射,具体化反射(reification) scala 从什么时候开始提供了反射API ? Scala 2.10 scala反射API的入口类是什么? Universe 主要的实现类有哪些? Types Symbols Trees Nam

[转载] 详述三种现代JVM语言--Groovy,Scala和Clojure

转载自http://www.tuicool.com/articles/jYzuAv和http://www.importnew.com/1537.html 在我与Martin Fowler曾经合作呈现的一次主题演讲中,他作出了一个有洞察性的观点: Java的遗产将是平台,而不是程序设计语言. Java技术的原始工程师们作出了一个明智的决定,就是将编程语言与运行时环境分开,最终这使得超过200种语言能够运行在Java平台上.这种架构对于该平台的长期活力是至关重要的,因为计算机程序设计语言的寿命一般都

Scala Structural Typing结构类型

鸭子类型:"当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子." 一般在动态语言里面才有,因为静态语言是强类型的,会在编译期检查类型,很难实现.但是Scala作为一门static type语言,居然支持,不得不说Scala确实很强大.直接上code package testscala object StructuralTyping extends App { def quacker(duck: {def quack(value: String): S

Scala之Object (apply) dycopy

一.前言 前面学习了Scala的Methods,接着学习Scala中的Object 二.Object Object在Scala有两种含义,在Java中,其代表一个类的实例,而在Scala中,其还是一个关键字,本篇首先将会把object当成一个类的实例看待,展示如何将对象从一种类型转化为另一种类型,之后将展示如何创建单例对象,Scala中还存在包对象,在Scala中,经常有如下定义 type Throwable = java.lang.Throwable type Exception = java

Scala 枚举: Enumeration 概述

Spark Scala 枚举 * Java 中的那套枚举并不能直接使用到 Scala 中* Scala 中的枚举使用轻量级 Enumeration 进行实现* Scala 中的枚举其实是一个伴随对象* Scala 中的枚举没有方法重写功能* Scala 中的枚举其实都是 Enumeration.Value 这个对象 和Java和C++不同,Scala并没有枚举类型.不过,Spark标准类库提供了一个 Enumeration类型,可以用于生成枚举,定义一个枚举类的对象,并以Value方法调用枚举中

scala简要:高级函数和高级类型

在scala中,函数是头等公民,可以用变量存储函数,可以使用匿名函数,和带参数的函数.如果需要一个序列的值,一般从一个简单序列转化得出.函数可以在变量不再作用域内时被调用,这样的函数叫闭包. 柯里化是指将原来接受两个参数变成接受一个参数的函数的过程.不需要用return语句来返回函数值,函数的返回值就是函数体的值. scala中,用方括号来定义类型参数,从调用该方法的实际参数来推断出类型.视图界定 T<%V要求必须存在一个从T到V的隐式转换,Manifest对象是构造器的隐式参数,可用于上下文界

(升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课程会涵盖Scala编程详解.Spark核心编程.Spark SQL和Spark Streaming.Spark内核以及源码剖析.性能调优.企业级案例实战等部分.完全从零起步,让学员可以一站式精通Spark企业级大数据开发,提升自己的职场竞争力,实现更好的升职或者跳槽,或者从j2ee等传统软件开发工程