1. Scala 的 反射
关于 Scala 反射的具体内容,可以参考官方文档:https://docs.scala-lang.org/overviews/reflection/overview.html
这篇文章写一点自己的理解:
先看基础代码:
package com.personal object ProvisioningApp { val strInObj = "123" def sayHello(): Unit = println("say hello") def sayHello2(from: String, to: String): Unit = println(from + " say hello, " + to) } class ProvisioningApp { val strInClazz = "234" def sayGoodbye(): Unit = println("say goodbye") }
2. Java Style
2.1 使用 Java 的方式反射 Scala class
和反射 Java 的 class 步骤完全一致,所以不赘述,直接贴代码:
test("Should reflect Scala class in Java style") { val app = new ProvisioningApp val field = classOf[ProvisioningApp].getDeclaredField("strInClazz") field.setAccessible(true) field.set(app, "789") app.strInClazz shouldBe "789" val method = classOf[ProvisioningApp].getDeclaredMethod("sayGoodbye") method.setAccessible(true) method.invoke(app) }
2.2 使用 Java 的方式反射 Scala object
Scala 中的 object,称之为 “伴生类”,想要反射获取它的类或者方法,首先要知道它编译之后是个什么东西:
通过 jd-gui,我们知道了 Scala object 的具体实现:
3. Scala style
3.1 使用 Scala 方式反射 Scala class
步骤如下:
test("Should reflect Scala class in Scala type") { import scala.reflect.runtime.universe val app = new ProvisioningApp() // JavaMirror val classMirror = universe.runtimeMirror(getClass.getClassLoader) // InstanceMirror val instanceMirror = classMirror.reflect(app) // TypeTag val typeTag = universe.typeOf[ProvisioningApp] // TermSymbol val strInClazzSymbol = typeTag.decl(universe.TermName("strInClazz")).asTerm val fieldMirror = instanceMirror.reflectField(strInClazzSymbol) fieldMirror.set("789") app.strInClazz shouldBe "789" // MethodSymbol val sayGoodbyeSymbol = typeTag.decl(universe.TermName("sayGoodbye")).asMethod // MethodMirror and invoke action val result = instanceMirror.reflectMethod(sayGoodbyeSymbol)() // No input parameters here result shouldBe "Goodbye" }
3.2 使用 Scala 方式反射 Scala object
与 Scala class 不同,反射 Scala object 核心是通过 staticModule 获取 ModuleMirror:
test("Should reflect Scala object in Scala style") { import scala.reflect.runtime.universe // JavaMirror val classMirror = universe.runtimeMirror(getClass.getClassLoader) // The ModuleSymbol for object val staticMirror = classMirror.staticModule("com.personal.ProvisioningApp") // ModuleMirror can be used to create instances of the class val moduleMirror = classMirror.reflectModule(staticMirror) // ObjectMirror can be used to reflect the members of the object val objectMirror = classMirror.reflect(moduleMirror.instance) // TermSymbol represents val, var, def and object declarations val strInObjSymbol = moduleMirror.symbol.typeSignature.member(universe.TermName("strInObj")).asTerm // FieldMirror can be used to get and set the value of the field val fieldMirror = objectMirror.reflectField(strInObjSymbol) fieldMirror.set("789") ProvisioningApp.strInObj shouldBe "789" val sayHelloSymbol = moduleMirror.symbol.typeSignature.member(universe.TermName("sayHello")).asMethod val sayHelloSymbol2 = moduleMirror.symbol.typeSignature.member(universe.TermName("sayHello2")).asMethod // MethodMirror and invoke action objectMirror.reflectMethod(sayHelloSymbol)() objectMirror.reflectMethod(sayHelloSymbol2)("Sai", "Gerrard") // Pass the input parameters one by one }
Scala进阶(1)—— 反射 object 和 class
原文:https://www.cnblogs.com/jing-an-feng-shao/p/14695057.html