【发布时间】:2019-08-14 17:07:35
【问题描述】:
我正在尝试使用 Java 反射在运行时替换对象字段的值,但以类型安全的方式。
假设我们有以下对象。
import cats.Eval
object Foo {
val bar: Eval[Int] = Eval.later(throw new Exception)
}
我们想在运行时更改Foo.bar 的值。我们可以使用普通的 Java 反射轻松定义以下方法:
import java.lang.reflect.Field
def usingJavaReflection[T](targetObject: AnyRef, fieldName: String)(newValue: T): Unit = {
val field = targetObject.getClass.getDeclaredField(fieldName)
field.setAccessible(true)
field.set(targetObject, newValue)
}
// usage
usingJavaReflection(Foo, "bar")(Eval.now(42))
现在问题变成了:如何以更类型安全的方式做到这一点?
def usingJavaReflectionButTypesafe[T](field: T)(newValue: T): Unit = ???
// intended usage
usingJavaReflectionButTypesafe(Foo.bar)(Eval.now(42))
这意味着能够做一些事情:
-
Foo.bar不应被评估 - 相反,
Foo.bar应分解为目标对象Foo和字段"bar" -
Foo.bar的类型应与newValue的类型相同
额外问题:如果这是可能的,如何使它适用于 Scala 2.11 和 2.12 和 2.13。我只是不知道哪些 Scala 宏技术在哪些版本的 Scala 中可以安全使用,以及如何使用。
【问题讨论】:
-
运行时反射在 JVM 上本质上是不安全的
标签: scala reflection scala-macros scala-cats