1.
其实scala的非FP部分,看官方DOC是一个非常好的一个选择,FP部分推荐还是看HASHELL,毕竟我看过的书籍中,FP部分基本是HASHELL的"翻译",HASHELL是个非常好的语言,甚至其作者是推荐作为大学的课本,你不必会用HASHELL编写程序,这个是很少见的,但是要有HASHELL语言的思考逻辑去学习一门FP语言,记得我接触HASHELL是大二的时候了,它对我的影响却是很大.
2.
scala的反射,scala的反射分为两个范畴运行时和编译时
这两者之间的区别在于Environment,而Environment又是由universe决定的.反射的另一个重要的部分就是一个实体集合,而这个实体集合被称为mirror,有了这个实体集合我们就可以实现对需要反射的类进行对应的操作,如属性的获取,属性值得设置,以及对反射类方法的调用(其实就是成员函数的入口地址)!
讲了这么多都觉得很饶了,说的直白一些就是要获取可以操作类方法或者属性的mirror,而mirror又是Environment得来的,而Environment又是Universes得来的,而Universes根据运行时和编译时又可以分为两个领域的
3.
Universes
根据反射的要求不同可分为
scala.reflect.runtime.universe for runtime reflection
scala.reflect.macros.Universe for compile-time reflection
4.
Mirrors
这个很重要,所以我还要再唠叨几句,Mirrors可以对"符号"(这里涉及到编译原理的知识,不讲解),进行不同的操作所以通常分为
“Classloader” mirrors
“Invoker” mirrors
"Classloader" mirrors 负责把对应的name转译称"符号",这些符号所对一的name实实的存在的,待会用例子就好理解了
"Invoker” mirrors 则是负责实现反射中的调用
5.运行时反射的实例
第一步: 获取Environment和universe
scala> val ru = scala.reflect.runtime.universe
ru: scala.reflect.api.JavaUniverse = scala.reflect.runtime.JavaUniverse@60cf3a
第二步: 获取对应的Mirrors,这里是运行时的
scala> val m = ru.runtimeMirror(getClass.getClassLoader)
m: ru.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClas
sLoader@150b551 of type class scala.tools.nsc.interpreter.IMain$TranslatingClass
Loader with classpath [(memory)] and parent being scala.reflect.internal.util.Sc
alaClassLoader$URLClassLoader@ac5762 of type class scala.reflect.internal.util.S
calaClassLoader$URLClassLoader with classpath [file:/D:/ProgramFiles/Java/jdk1.8
.0_31/jre/lib/resources.jar,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/rt.ja
r,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/jsse.jar,file:/D:/ProgramFiles/
Java/jdk1.8.0_31/jre/lib/jce.jar,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/
charsets.jar,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/jfr.jar,file:/D:/Pro
gramFiles/Java/jdk1.8.0_31/jre/lib/ext/access-bridge.jar,file:/D:/ProgramFile...
第三步: 用Mirrors去reflect对应的类,返回一个Mirrors的实例,而该Mirrors装载着对应类的信息
scala> class C { def x = 2 }
defined class C
warning: previously defined object C is not a companion to class C.
Companions must be defined together; you may wish to use :paste mode for this.
scala> val im = m.reflect(new C)
im: ru.InstanceMirror = instance mirror for C@b55a0e
scala>
此时我们把一个类的信息"加载"完毕了,接下来我们来"反射"里面的信息,不过在反射之前我们要构建对应的符号(这个是我们上面介绍的,不懂没关系,会用就行)
第四步:符号
这里我们创建class C中变量x的符号
scala> val methodX = ru.typeOf[C].declaration(ru.TermName("x")).asMethod
warning: there was one deprecation warning; re-run with -deprecation for details
methodX: ru.MethodSymbol = method x
有了符号,我们就可以根据这个符号来向Mirrors"索求"我们的需要的东西了(这个就是反射了)
第五步:反射
scala> val mm = im.reflectMethod(methodX)
mm: ru.MethodMirror = method mirror for def x: scala.Int (bound to C@b55a0e)
第六步:已经反射到方法了,接下来...
scala> mm
res7: ru.MethodMirror = method mirror for def x: scala.Int (bound to C@b55a0e)
scala> mm()
res8: Any = 2
其实映射后我们并不是直接拿到该属性或者方法的,这是一个绑定,记住!
其他:
反射属性:
scala> class C { val x = 2; var y = 3 }
defined class C
warning: previously defined object C is not a companion to class C.
Companions must be defined together; you may wish to use :paste mode for this.
scala> class D { val x = 2; var y = 3 }
defined class D
scala> val m = ru.runtimeMirror(getClass.getClassLoader)
m: ru.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClas
sLoader@150b551 of type class scala.tools.nsc.interpreter.IMain$TranslatingClass
Loader with classpath [(memory)] and parent being scala.reflect.internal.util.Sc
alaClassLoader$URLClassLoader@ac5762 of type class scala.reflect.internal.util.S
calaClassLoader$URLClassLoader with classpath [file:/D:/ProgramFiles/Java/jdk1.8
.0_31/jre/lib/resources.jar,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/rt.ja
r,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/jsse.jar,file:/D:/ProgramFiles/
Java/jdk1.8.0_31/jre/lib/jce.jar,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/
charsets.jar,file:/D:/ProgramFiles/Java/jdk1.8.0_31/jre/lib/jfr.jar,file:/D:/Pro
gramFiles/Java/jdk1.8.0_31/jre/lib/ext/access-bridge.jar,file:/D:/ProgramFile...
scala> val im = m.reflect(new D)
im: ru.InstanceMirror = instance mirror for D@119430f
scala> val fieldX = ru.typeOf[D].declaration(ru.TermName("x")).asTerm.accessed.a
sTerm
warning: there was one deprecation warning; re-run with -deprecation for details
fieldX: ru.TermSymbol = value x
scala> val fmX = im.reflectField(fieldX)
fmX: ru.FieldMirror = field mirror for private[this] val x: scala.Int (bound to
D@119430f)
scala> fmX.get
res9: Any = 2
scala> fmX.set(5)
scala> fmX.get
res11: Any = 5
这个是粗率的讲解scala反射,详细的
http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html