获取包对象上字段的FieldMirror



我需要使用反射来获取在包对象上定义的字段。

package com.coryklein
package object kittens {
  val purr = "meow"
}

mirror文档说:

Scala只有实例方法——对象的方法是对象实例的实例方法,可通过ModuleMirror.instance

获得

甚至有一个很好的例子,使用反射在一个已定义的类C上调用方法x

scala> class C { def x = 2 }
defined class C
scala> val im = m.reflect(new C)
im: reflect.runtime.universe.InstanceMirror = instance mirror for C@3442299e
scala> val methodX = typeOf[C].declaration(TermName("x")).asMethod
methodX: reflect.runtime.universe.MethodSymbol = method x
scala> val mm = im.reflectMethod(methodX)
mm: reflect.runtime.universe.MethodMirror = method mirror for C.x: scala.Int (bound to C@3442299e)
scala> mm()
res0: Any = 2

从这里看来,适应这种方法来反映存在于包对象上的字段应该不是太困难。但是,包对象没有相应的类来通过反射获取该字段。

我已经能够获得术语符号:

val ts: TermSymbol = mirror.staticPackage("com.coryklein.kittens").info.decls
  .find(_.name.decodedName.toString == "purr").get.asTerm

但是在这一点上,我没有一个实例镜像等价于上面的im来反射这个字段。

我如何通过Scala反射访问在包对象kittens中定义的purr val ?

这里的关键部分是找到实际的模块,它最终被命名为com.coryklein.kittens.package$:

scala>  import scala.reflect.runtime.{ universe => ru }
import scala.reflect.runtime.{universe=>ru}
scala> val runtimeMirror  = ru.runtimeMirror(getClass.getClassLoader)
runtimeMirror: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@67ee3ed7 of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)] and parent being scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@53b79b76 of type class scala.reflect.internal.util.ScalaClassLoader$URLClassLoader with classpath [file:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/resources.jar,file:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/rt.jar,file:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jsse.jar,file:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jce.jar,file:/Library/Jav...
scala> val moduleSymbol   = runtimeMirror.staticModule("com.coryklein.kittens.package$")
moduleSymbol: reflect.runtime.universe.ModuleSymbol = object package$
scala> val moduleMirror   = runtimeMirror.reflectModule(moduleSymbol)
moduleMirror: reflect.runtime.universe.ModuleMirror = module mirror for com.coryklein.kittens.package$ (bound to null)
scala> val moduleInstance = moduleMirror.instance
moduleInstance: Any = com.coryklein.kittens.package$@72d3f96
scala> val instanceMirror = runtimeMirror.reflect(moduleInstance)
instanceMirror: reflect.runtime.universe.InstanceMirror = instance mirror for com.coryklein.kittens.package$@72d3f96
scala> val fieldSymbol    = instanceMirror.symbol.info.member(ru.TermName("purr")).asTerm.accessed.asTerm
fieldSymbol: reflect.runtime.universe.TermSymbol = value purr
scala> val fieldMirror    = instanceMirror.reflectField(fieldSymbol)
fieldMirror: reflect.runtime.universe.FieldMirror = field mirror for private[this] val purr: java.lang.String (bound to com.coryklein.kittens.package$@72d3f96)
scala> fieldMirror.get
res0: Any = meow
scala>

我通过在我的target/scala-2.12/classes目录中戳出模块的名称,并在这里和那里运行javap

相关内容

  • 没有找到相关文章

最新更新