给定以下类层次结构:
class A {
val x = 3
val y = 4
}
class B extends A {
val x = 4
}
并说我有一个B实例,没有编译时的类层次结构知识,并希望能够报告如下内容:
Class: B
val[x]: 3
val[y]: 4
val[z]: 5
使用scala反射的最佳方法是什么?
由于 Des
答案 0 :(得分:14)
简而言之:
import scala.reflect.runtime.universe._
val a = new A
val rm = scala.reflect.runtime.currentMirror
val accessors = rm.classSymbol(a.getClass).toType.members.collect {
case m: MethodSymbol if m.isGetter && m.isPublic => m
}
val instanceMirror = rm.reflect(a)
for(acc <- accessors)
println(s"$a: ${instanceMirror.reflectMethod(acc).apply()}")
答案 1 :(得分:1)
您可以通过TypeTag获取访问权限:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> class A {
| val x = 3
| val y = 4
| }
defined class A
scala> class B extends A {
| val z = 5
| }
defined class B
scala> typeOf[B]
res0: reflect.runtime.universe.Type = B
现在您有两个选项:members
显示所有成员(甚至是继承的成员)和declarations
(仅在当前类中定义),例如:
scala> res0.declarations
res2: reflect.runtime.universe.MemberScope = SynchronizedOps(constructor B, value z, value z)
如果您想使用此字段,则需要通过InstanceMirror反映它们:
scala> val b = new B
b: B = B@6ebe10dd
scala> val currentMirror = runtimeMirror(getClass.getClassLoader)
.....
scala> val bMir = currentMirror.reflect(b)
bMir: reflect.runtime.universe.InstanceMirror = instance mirror for B@6ebe10dd
现在您只需要获得所需的符号,例如,您希望获得z
变量的值:
scala> val zt = typeOf[B].declaration("z": TermName).asMethod
zt: reflect.runtime.universe.MethodSymbol = value z
scala> bMir.reflectField(zt).get
res20: Any = 5
答案 2 :(得分:0)
这是另一种方法:
scala> val i = 10
i: Int = 10
scala> val ru=scala.reflect.runtime.universe
ru: scala.reflect.api.JavaUniverse = scala.reflect.runtime.JavaUniverse@2096fb9f
scala> val m = ru.runtimeMirror(getClass.getClassLoader)
m: ru.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@3ae5ce58 of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)] and parent being scala.tools.nsc.util.ScalaClassLoader$URLClassLoader@454e119d of type class scala.tools.nsc.util.ScalaClassLoader$URLClassLoader with classpath [file:/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/resources.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/rt.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/jsse.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/jce.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/charsets.jar,file:...
scala> val im=m.reflect(i)
im: ru.InstanceMirror = instance mirror for 10
scala> val is =im.symbol
is: ru.ClassSymbol = class Int
scala> val ims=is.toType.members
ims: ru.MemberScope = Scopes(method getClass, constructor Int, method ##, method asInstanceOf, method isInstanceOf, method toString, method hashCode, method equals, method !=, method ==, method %, method %, method %, method %, method %, method %, method %, method /, method /, method /, method /, method /, method /, method /, method *, method *, method *, method *, method *, method *, method *, method -, method -, method -, method -, method -, method -, method -, method +, method +, method +, method +, method +, method +, method +, method ^, method ^, method ^, method ^, method ^, method &, method &, method &, method &, method &, method |, method |, method |, method |, method |, method >=, method >=, method >=, method >=, method >=, method >=, method >=, method >, method >, method >, met...
scala>
然后可以按照您喜欢的方式进一步过滤 ims
。