简体   繁体   English

Scala 中 Java 反射的类型安全使用

[英]Type-safe usage of Java reflection in Scala

I am trying to use Java reflection to replace the value for an object's field at runtime, but in a type-safe way.我正在尝试使用 Java 反射在运行时替换对象字段的值,但以类型安全的方式。

Let's assume we have the following object.假设我们有以下对象。

import cats.Eval

object Foo {
  val bar: Eval[Int] = Eval.later(throw new Exception)
}

We want to change the value for Foo.bar at runtime.我们想在运行时更改Foo.bar的值。 We can easily define the following method using normal Java reflection:我们可以使用普通的 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))

Now the question becomes: how to do that in a more type-safe way?现在问题变成了:如何以更类型安全的方式做到这一点?

def usingJavaReflectionButTypesafe[T](field: T)(newValue: T): Unit = ???

// intended usage
usingJavaReflectionButTypesafe(Foo.bar)(Eval.now(42))

This means being able to do a few things:这意味着能够做一些事情:

  1. Foo.bar should not be evaluated Foo.bar不应该被评估
  2. Instead, Foo.bar should be broken down into a target object Foo and a field "bar"相反,应该将Foo.bar分解为目标对象Foo和字段"bar"
  3. The type for Foo.bar should be the same as for newValue Foo.bar的类型应该与newValue的类型相同

Bonus question: If this is possible, how to make it work for Scala 2.11 and 2.12 and 2.13.额外问题:如果可能,如何使其适用于 Scala 2.11、2.12 和 2.13。 I just cannot wrap my head around which Scala macros techniques are safe to use in which versions of Scala, and how.我无法确定哪些 Scala 宏技术可以安全地用于哪些 Scala 版本以及如何使用。

Try尝试

def usingJavaReflectionButTypesafe[T](field: => T)(newValue: T): Unit = macro impl[T]

def impl[T: c.WeakTypeTag](c: blackbox.Context)(field: c.Tree)(newValue: c.Tree): c.Tree = {
  import c.universe._
  field match {
    case q"$expr.$tname" =>
      q"usingJavaReflection($expr, ${tname.toString})($newValue)"
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM