1. 运行时反射
scala编译器会将scala代码编译成JVM字节码,编译过程中会擦除scala特有的一些类型信息,在scala-2.10以前,只能在scala中利用java的反射机制,但是通过java反射机制得到的是只是擦除后的类型信息,并不包括scala的一些特定类型信息。从scala-2.10起,scala实现了自己的反射机制,我们可以通过scala的反射机制得到scala的类型信息。
给定类型或者对象实例,通过scala运行时反射,可以做到:1)获取运行时类型信息;2)通过类型信息实例化新对象;3)访问或调用对象的方法和属性等。
2. 代码演示反射过程
用于反射的类型
package com.liu.scala.reflect
import scala.beans.BeanProperty
/**
* Created by xiaoliu
*/
class Person {
@BeanProperty var name:String = _
def speak(s:String):Unit = {
println(s"[$name]讲了:$s")
}
}
反射过程
package com.liu.scala.reflect /** * Created by xiaoliu */ object Main { def main(args: Array[String]): Unit = { // 直接创建的方式 val p = new Person p.setName("刘先生") p.speak("晚安!") // 反射方式 reflectMethod() } def reflectMethod() = { //获取Environment和universe val ru = scala.reflect.runtime.universe //获取对应的Mirrors,这里是运行时的 val mirror = ru.runtimeMirror(getClass.getClassLoader) //得到Person类的Type对象后,得到type的特征值并转为ClassSymbol对象 val classPerson = ru.typeOf[Person].typeSymbol.asClass //用Mirrors去reflect对应的类,返回一个Mirrors的实例,而该Mirrors装载着对应类的信息 val classMirror = mirror.reflectClass(classPerson) //得到构造器Method val constructor = ru.typeOf[Person].decl(ru.termNames.CONSTRUCTOR).asMethod //得到MethodMirror val methodMirror = classMirror.reflectConstructor(constructor) //实例化该对象 val p = methodMirror() println(p) //反射方法并调用 val instanceMirror = mirror.reflect(p) //得到Method的Mirror val myPrintMethod = ru.typeOf[Person].decl(ru.TermName("speak")).asMethod //通过Method的Mirror索取方法 val speak = instanceMirror.reflectMethod(myPrintMethod) val nameField = ru.typeOf[Person].decl(ru.TermName("name")).asTerm val name = instanceMirror.reflectField(nameField) name.set("刘先生") //运行myPrint方法 speak("早!") //得到属性Field的Mirror } }
3. 运行结果