gpt4 book ai didi

scala - 如何通过反射获取Scala特化字段参数的原始数据类型?

转载 作者:行者123 更新时间:2023-12-02 05:36:42 26 4
gpt4 key购买 nike

我有一个类,它有一个专门的字段并使用原始数据类型。例如一个 Tuple2[Int, String]:

scala> class TupleReflection(val tuple: Tuple2[Int, String])
defined class TupleReflection

scala> val refl = new TupleReflection((5, "hello"))
refl: TupleReflection = TupleReflection@1a597ec8

我现在想使用反射来找出“refl”实例中 Tuple2 的类型参数。 (我使用“head”来获取字段,因为我知道它是唯一的。)

scala> val field = refl.getClass.getDeclaredFields.head
field: java.lang.reflect.Field = private final scala.Tuple2 TupleReflection.tuple

现在我有了可以查询泛型类型的字段。

scala> field.getGenericType
res41: java.lang.reflect.Type = scala.Tuple2<java.lang.Object, java.lang.String>

现在的问题是第一个类型是Object。有没有办法仅通过反射就知道该参数的实际类型 (Int)?

更新:

我在我自己的 API 中的自动序列化上下文中使用它。给定一个标有 @Serializable 的类,我可以序列化它。为此,我必须使用反射递归地构建类的字段和类型的树,以便我可以进行深度序列化。

如果我直接使用 @Specialized 类,它可以工作,因为类型是显式的,并且在编译时在调用站点已知。如果层次结构中的字段是 @specialized 我无法通过反射来判断。查询类中声明的字段或方法不会产生正确的值。该类型存在于运行时,但仅存在于字段中的实例中,而不存在于字段本身的声明中。因此,如果实例为 null 并且不能执行“getClass”,我无法仅通过反射知道正确的类型。

最佳答案

问题是您使用的 Java 反射 API 无法解决 JVM 的“类型删除”问题,因为无法通过它找出实际的泛型类型。

幸运的是,即将到来的 2.10 版本的 Scala 实现了新的反射 API,解决了类型删除问题。但由于 2.10 尚未发布,API 尚未标准化或记录在案。最好的办法是使用调试器等工具深入研究它,并提出此处出现的更具体的问题。

在 Scala 2.10-M5 中,您可以像下面这样访问 API:

scala> reflect.runtime.universe.typeOf[(Int, String)]
res0: reflect.runtime.universe.Type = (Int, String)

scala> reflect.runtime.universe.typeOf[(Int, String)].typeArguments
res1: List[reflect.runtime.universe.Type] = List(Int, String)

scala> reflect.runtime.universe.typeOf[(Int, String)].typeArguments.head
res2: reflect.runtime.universe.Type = Int

更新#1

以下函数显示了如何获取实例类型:

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> def typeOf[T : TypeTag](x : T) = reflect.runtime.universe.typeOf[T]
typeOf: [T](x: T)(implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type

scala> typeOf(Seq((1,"sldf"),(20,"sldkfjew")))
res0: reflect.runtime.universe.Type = Seq[(Int, String)]

事实上,它都是基于 [T : TypeTag] 部分,它告诉编译器神奇地创建一个反射到传递类型的隐式实例。

更新#2

scala> class TupleReflection(val tuple: Tuple2[Int, String])
defined class TupleReflection

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> typeOf[TupleReflection].member(newTermName("tuple")).typeSignature
res6: reflect.runtime.universe.Type = => (scala.Int, String)

scala> typeOf[TupleReflection].members
res7: Iterable[reflect.runtime.universe.Symbol] = List(constructor TupleReflection, value tuple, value tuple, method $asInstanceOf, method $isInstanceOf, method synchronized, method ##, method !=, method ==, method ne, method eq, constructor Object, method notifyAll, method notify, method clone, method getClass, method hashCode, method toString, method equals, method wait, method wait, method wait, method finalize, method asInstanceOf, method isInstanceOf, method !=, method ==)

scala> typeOf[TupleReflection].members.view.filter(_.isValue).filter(!_.isMethod).toList
res16: List[reflect.runtime.universe.Symbol] = List(value tuple)

关于scala - 如何通过反射获取Scala特化字段参数的原始数据类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11586944/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com