假设我有一个带有懒惰成员的案例类
case class Person(name: String, surname: String) {
lazy val initials: String = name(0) + "." + surname(0) + "."
}
而且我有一个通用函数将其转换为Map
def getCCParams(cc: AnyRef) =
cc.getClass.getDeclaredFields.map { f =>
f.setAccessible(true)
f.getName -> f.get(cc)
}.toMap
现在创建一个人并获取其值
val JohnSmith = Person("John", "Smith")
val res = getCCParams(JohnSmith)
println(res)
因此我得到结果
HashMap(initials -> null, name -> John, surname -> Smith)
initials等于null,因为未调用它。有什么方法可以激活getCCParams
函数中的惰性值?我可以作为参数传递的惰性成员列表
def getCCParams(cc: AnyRef, lazyMembers: List[String] = List("initials")) = ...
谢谢
第一次调用accessor方法时,将初始化惰性val。因此,也许您可以调用这些方法,而不是尝试直接访问字段?
def getCCParams(cc: AnyRef) = {
val clazz = cc.getClass
clazz.getDeclaredFields.flatMap { f =>
Try(clazz.getMethod(f.getName)) //get the accessor method by name of field
.toOption
.map(m => f.getName -> m.invoke(cc))
}.toMap
}
结果:Map(initials -> J.S., name -> John, surname -> Smith)
[lazy val initials = "J.S."
扩展为类似
lazy var initials: String = _;
var bitmap$0: Boolean = _;
private def initials$lzycompute(): String = {
if (!bitmap$0)
{
initials = ("J.S.": String);
bitmap$0 = true
};
iw.this.initials
};
lazy def initials(): String =
if (!bitmap$0)
initials$lzycompute()
else
initials;
我们注意到相应的initials$lzycompute
方法实际上设置了initials
。因此,在获取类似字段之前尝试调用它
def getCCParams(cc: AnyRef, lazyMembers: List[String] = Nil) = {
lazyMembers.foreach { lazyMember =>
val postfix = "$lzycompute"
val method = cc.getClass.getDeclaredMethod(s"$lazyMember$postfix")
method.setAccessible(true)
method.invoke(cc)
}
cc.getClass.getDeclaredFields.map { f =>
f.setAccessible(true)
f.getName -> f.get(cc)
}.toMap
}
现在
val JohnSmith = Person("John", "Smith")
val res = getCCParams(JohnSmith, List("initials"))
res
输出
HashMap(name -> John, initials -> J.S., surname -> Smith, $outer -> example.A$A0$A$A0@ba325fb, bitmap$0 -> true)