我需要使用反射来获取在包对象上定义的字段。
package com.coryklein
package object kittens {
val purr = "meow"
}
Scala只有实例方法 - 对象的方法是对象实例的实例方法,可通过ModuleMirror.instance获取
甚至有一个慷慨的例子,使用反射来调用已定义的类x
上的方法C
。
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
从这里开始,似乎不太难以使方法适应反映包对象上存在的字段。但是,包对象没有相应的类来从via反射中获取字段。
我能够获得术语符号:
val ts: TermSymbol = mirror.staticPackage("com.coryklein.kittens").info.decls
.find(_.name.decodedName.toString == "purr").get.asTerm
但是在这一点上,我没有一个等同于im
的实例镜像来反映这个字段。
如何通过Scala反射访问包对象purr
中定义的kittens
val?
答案 0 :(得分:2)
这里的关键部分是找到实际模块,最终命名为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
。