Scala 获取对象的字段值并将其写入映射
我正在尝试将对象状态(带有特定字段)镜像到映射中Scala 获取对象的字段值并将其写入映射,scala,reflection,Scala,Reflection,我正在尝试将对象状态(带有特定字段)镜像到映射中 class ObjectState[T] { // object reference var objRef : T = _ // map that mirrors current object state var stateMap : Map[String, Any] = _ def registerFields(fields: List[String], objectInstance: T): Unit = { /
class ObjectState[T] {
// object reference
var objRef : T = _
// map that mirrors current object state
var stateMap : Map[String, Any] = _
def registerFields(fields: List[String], objectInstance: T): Unit = {
// just register
objRef = objectInstance
stateMap = fields.map(field => field -> null)(collection.breakOut)
Mirror.inMirrorObjectState(this)
}
object Mirror {
// basically populate object state
def inMirrorObjectState[T](state: ObjectState[T]): Unit = {
val objectInstance = state.objRef
stateMap.keySet foreach { key =>
println(s"Attempt to find ${key}")
println(s"Fields: ${objectInstance.getClass.getFields.size}") // zero field size
val field = objectInstance.getClass.getField(key) // exception
stateMap += (key -> field.get(objectInstance))
}
}
}
}
我的对象实例如下所示
val obj = new BasicObject
obj.fieldA = "field"
obj.fieldB = 10
// 1. register object in OSM and get id - might be useful
val id = OSMPlatform.registerObject(obj, List("fieldA", "fieldB"))
class BasicObject {
var fieldA : String = _
var fieldB : Int = _
override def toString: String = {
"Basic object: $fieldA : $fieldB"
}
}
类BasicObject
如下所示
val obj = new BasicObject
obj.fieldA = "field"
obj.fieldB = 10
// 1. register object in OSM and get id - might be useful
val id = OSMPlatform.registerObject(obj, List("fieldA", "fieldB"))
class BasicObject {
var fieldA : String = _
var fieldB : Int = _
override def toString: String = {
"Basic object: $fieldA : $fieldB"
}
}
然后我尝试创建我的ObjectState
类的实例
def registerObject(objectInstance: AnyRef, fields: List[String]): String = {
val id = UUID.randomUUID().toString
val objState = new ObjectState[AnyRef]
objState.registerFields(fields, objectInstance)
OSMContext.registerObject(id, objState)
id
}
但我得到了一个例外
Exception in thread "main" java.lang.NoSuchFieldException: fieldA
在那条线上
val field = objectInstance.getClass.getField(key)
似乎找不到那块地。为什么呢?这是由于
T
类型造成的吗?基于我的跑步记录,您应该使用:getDeclaredField
并使用setAccessible(true)
来避开非法访问异常
class ObjectState[T] {
// object reference
var objRef : T = _
// map that mirrors current object state
var stateMap : Map[String, Any] = _
def registerFields(fields: List[String], objectInstance: T): Unit = {
// just register
objRef = objectInstance
stateMap = fields.map(field => field -> null)(collection.breakOut)
Mirror.inMirrorObjectState(this)
}
object Mirror {
// basically populate object state
def inMirrorObjectState[T](state: ObjectState[T]): Unit = {
val objectInstance = state.objRef
stateMap.keySet foreach { key =>
println(s"Attempt to find ${key}")
// zero field size
val value = objectInstance.getClass.getDeclaredField(key) // exception
value.setAccessible(true) // remote the IllegalAccessException
stateMap += (key -> value.get(objectInstance))
}
}
}
}
class Name () {
var name: String = _
}
val obj = new Name();
obj.name = "H"
val objState = new ObjectState[AnyRef];
objState.registerFields(List("name"), obj);
objState.stateMap
希望这会有所帮助,但我认为对我来说使用setAccessible api就像是一个黑客
似乎这样更好,删除setAccessible并使用getDeclaredMethod(名称的获取者)然后调用它
scala> class ObjectState[T] {
| // object reference
| var objRef : T = _
| // map that mirrors current object state
| var stateMap : Map[String, Any] = _
|
| def registerFields(fields: List[String], objectInstance: T): Unit = {
| // just register
| objRef = objectInstance
| stateMap = fields.map(field => field -> null)(collection.breakOut)
| Mirror.inMirrorObjectState(this)
| }
|
| object Mirror {
| // basically populate object state
| def inMirrorObjectState[T](state: ObjectState[T]): Unit = {
| val objectInstance = state.objRef
| stateMap.keySet foreach { key =>
| println(s"Attempt to find ${key}")
| // zero field size
| val value = objectInstance.getClass.getDeclaredMethod(key) // exception
| stateMap += (key -> value.invoke(objectInstance))
| }
| }
| }
| }
defined class ObjectState
scala>
scala> class Name () {
| var name: String = _
| }
defined class Name
scala>
scala> val obj = new Name();
obj: Name = Name@fb21b91
scala> obj.name = "H"
obj.name: String = H
scala>
scala> val objState = new ObjectState[AnyRef];
objState: ObjectState[AnyRef] = ObjectState@688bf369
scala> objState.registerFields(List("name"), obj);
Attempt to find name
scala> objState.stateMap
res1: Map[String,Any] = Map(name -> H)
根据我的跑步记录,您应该使用:
getDeclaredField
,也可以使用setAccessible(true)
来避开IllegaAccessException
class ObjectState[T] {
// object reference
var objRef : T = _
// map that mirrors current object state
var stateMap : Map[String, Any] = _
def registerFields(fields: List[String], objectInstance: T): Unit = {
// just register
objRef = objectInstance
stateMap = fields.map(field => field -> null)(collection.breakOut)
Mirror.inMirrorObjectState(this)
}
object Mirror {
// basically populate object state
def inMirrorObjectState[T](state: ObjectState[T]): Unit = {
val objectInstance = state.objRef
stateMap.keySet foreach { key =>
println(s"Attempt to find ${key}")
// zero field size
val value = objectInstance.getClass.getDeclaredField(key) // exception
value.setAccessible(true) // remote the IllegalAccessException
stateMap += (key -> value.get(objectInstance))
}
}
}
}
class Name () {
var name: String = _
}
val obj = new Name();
obj.name = "H"
val objState = new ObjectState[AnyRef];
objState.registerFields(List("name"), obj);
objState.stateMap
希望这会有所帮助,但我认为对我来说使用setAccessible api就像是一个黑客
似乎这样更好,删除setAccessible并使用getDeclaredMethod(名称的获取者)然后调用它
scala> class ObjectState[T] {
| // object reference
| var objRef : T = _
| // map that mirrors current object state
| var stateMap : Map[String, Any] = _
|
| def registerFields(fields: List[String], objectInstance: T): Unit = {
| // just register
| objRef = objectInstance
| stateMap = fields.map(field => field -> null)(collection.breakOut)
| Mirror.inMirrorObjectState(this)
| }
|
| object Mirror {
| // basically populate object state
| def inMirrorObjectState[T](state: ObjectState[T]): Unit = {
| val objectInstance = state.objRef
| stateMap.keySet foreach { key =>
| println(s"Attempt to find ${key}")
| // zero field size
| val value = objectInstance.getClass.getDeclaredMethod(key) // exception
| stateMap += (key -> value.invoke(objectInstance))
| }
| }
| }
| }
defined class ObjectState
scala>
scala> class Name () {
| var name: String = _
| }
defined class Name
scala>
scala> val obj = new Name();
obj: Name = Name@fb21b91
scala> obj.name = "H"
obj.name: String = H
scala>
scala> val objState = new ObjectState[AnyRef];
objState: ObjectState[AnyRef] = ObjectState@688bf369
scala> objState.registerFields(List("name"), obj);
Attempt to find name
scala> objState.stateMap
res1: Map[String,Any] = Map(name -> H)
是否也可以添加BasicObject定义,与BasicObject实例和registerFields调用没有当前关系。@LostMoican完成是否也可以添加BasicObject定义,与BasicObject实例和registerFields调用没有当前关系。@LostMoican完成