我正在使用scala中的反射。我选择了
class CloneSubject(val a :Int, b :String, private var c :Boolean)
作为主题并迭代typeOf[CloneSubject].members
以查找字段(sym.isTerm && (sym.asTerm.isVar || sym.asTerm.isVal)
)但是当我尝试创建FieldMirror时,(cm mirrorField sym.asTerm
)我得到此异常:
Exception in thread "main" scala.ScalaReflectionException: Scala field b isn't represented as a Java field,
neither it has a Java accessor method
note that private parameters of class constructors don't get mapped onto fields and/or accessors,
unless they are used outside of their declaring constructors.`
现在,我完全理解为什么会发生这种情况,但我无法找到一种方法来检查这一点而不会抛出异常。当然,使用Java反射工作得很好,但那是违背这一点的。有什么想法吗?
答案 0 :(得分:1)
要避免错误,请事先过滤掉b
:
scala> val m = reflect.runtime.universe.runtimeMirror(getClass.getClassLoader)
m: reflect.runtime.universe.Mirror = JavaMirror with ...
scala> val im = m.reflect(new CloneSubject(5, "hello", true))
im: reflect.runtime.universe.InstanceMirror = instance mirror for CloneSubject@2a95e173
scala> val fields = typeOf[CloneSubject].members collect { case m: MethodSymbol if m.isGetter => m.accessed }
fields: Iterable[reflect.runtime.universe.Symbol] = List(variable c, value a)
scala> fields map (s => im.reflectField(s.asTerm).get)
res45: Iterable[Any] = List(true, 5)
您知道可以访问的每个字段都有一个Getter,因此唯一要做的就是获取所有现有Getters所代表的字段。
使用它来检查val / var是否具有Getter的另一个选项:
scala> typeOf[CloneSubject].members.filter(s => s.isTerm && (s.asTerm.isVar || s.asTerm.isVal) && s.asTerm.getter != NoSymbol)
res50: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(variable c, value a)
答案 1 :(得分:1)
要用隐形墨水书写,你可以使用柠檬汁:
scala> typeOf[CloneSubject].members.collect { case s if s.name.decoded.endsWith(" ") => s }
res9: Iterable[reflect.runtime.universe.Symbol] = List(variable c, value a)
scala> cm reflect new CloneSubject(8, "foo", true)
res11: reflect.runtime.universe.InstanceMirror = instance mirror for CloneSubject@cdeca29
scala> res9 map (res11 reflectField _.asTerm) map (_.get)
res12: Iterable[Any] = List(true, 8)
神秘的空间是:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> nme.
CONSTRUCTOR EMPTY EMPTY_PACKAGE_NAME ERROR
LOCAL_SUFFIX_STRING NameType PACKAGE ROOTPKG
WILDCARD asInstanceOf isInstanceOf toString
scala> nme.LOCAL_SUFFIX_STRING
res0: String = " "