【问题标题】:Access private field in Companion object访问 Companion 对象中的私有字段
【发布时间】:2017-11-30 05:54:09
【问题描述】:

我有一个带有伴随对象的类TestClass。当从类中设置私有字段时,如何使用scala中的运行时反射访问伴生对象中的私有字段xyz,如下所示。

class TestClass {  TestClass.xyz = 100 }
object TestClass { private var xyz: Int = _ }

我尝试了以下

import scala.reflect.runtime.{currentMirror, universe => ru}
val testModuleSymbol = ru.typeOf[TestClass.type].termSymbol.asModule
val moduleMirror = currentMirror.reflectModule(testModuleSymbol)
val instanceMirror = currentMirror.reflect(moduleMirror.instance)
val xyzTerm = ru.typeOf[TestClass.type].decl(ru.TermName("xyz")).asTerm.accessed.asTerm
val fieldMirror = instanceMirror.reflectField(xyzTerm)
val context = fieldMirror.get.asInstanceOf[Int]

但我收到以下错误。

scala> val fieldMirror = instanceMirror.reflectField(xyzTerm)
scala.ScalaReflectionException: Scala field xyz  of object TestClass isn't represented as a Java field, nor does it have a
Java accessor method. One common reason for this is that it may be a private class parameter
not used outside the primary constructor.
  at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$abort(JavaMirrors.scala:115)
  at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$ErrorNonExistentField(JavaMirrors.scala:127)
  at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:242)
  at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:233)
  ... 29 elided

仅当我在TestClass 中引用变量xyz(即TestClass.xyz = 100)时才会引发此异常。如果从类中删除此引用,那么我的示例代码就可以正常工作。

【问题讨论】:

    标签: scala reflection


    【解决方案1】:

    让这个工作:

    import scala.reflect.runtime.universe._
    import scala.reflect.runtime.{universe => ru}
    
    val runMirror = ru.runtimeMirror(getClass.getClassLoader)
    val objectDef = Class.forName("org.myorg.TestClass")
    val objectTypeModule = runMirror.moduleSymbol(objectDef).asModule
    val objectType = objectTypeModule.typeSignature
    
    val methodMap = objectType.members
      .filter(_.isMethod)
      .map(d => {
        d.name.toString -> d.asMethod
      })
      .toMap
    
    // get the scala Object
    val instance = runMirror.reflectModule(objectTypeModule).instance
    val instanceMirror = runMirror.reflect(instance)
    // get the private value
    val result = instanceMirror.reflectMethod(methodMap("xyz")).apply()
    assert(result == 100)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-07
      • 2013-06-06
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多