gpt4 book ai didi

java - 如何在 Scala 运行时获取泛型类型

转载 作者:行者123 更新时间:2023-11-29 04:46:14 24 4
gpt4 key购买 nike

我有一个跟类

package myapp.model

case class Person(
name: String,
age: Option[Int]
)

我想实现以下功能:

def getFieldClass(className: String, fieldName:String): java.lang.Class[_] = {
// case normal field return its class
// case Option field return generic type of Option
}

因此对于以下输入:

  • className="myapp.model.Person"
  • fieldName="年龄"

该函数将返回类对象:scala.Int


使用 Java Reflection API 的解决方案效果不佳,它为 Option[Int] 返回 java.lang.Object:

def getFieldClass(className: String, fieldName:String): java.lang.Class[_] = {
val cls = java.lang.Class.forName(className)
val pt = cls.getDeclaredField(fieldName).getGenericType.asInstanceOf[java.lang.reflect.ParameterizedType]
val tpe = pt.getActualTypeArguments()(0);
java.lang.Class.forName(tpe.getTypeName)
}

我正在编写反序列化功能的一部分,但我没有检查其类型的对象,我只有一个类名。

最佳答案

您可以使用 Scala 的反射库来完成此任务。

虽然它不是特别漂亮:

import scala.reflect.runtime.{ universe => u }
import scala.reflect.runtime.universe._

object ReflectionHelper {

val classLoader = Thread.currentThread().getContextClassLoader

val mirror = u.runtimeMirror(classLoader)

def getFieldType(className: String, fieldName: String): Option[Type] = {

val classSymbol = mirror.staticClass(className)

for {
fieldSymbol <- classSymbol.selfType.members.collectFirst({
case s: Symbol if s.isPublic && s.name.decodedName.toString() == fieldName => s
})
} yield {

fieldSymbol.info.resultType
}
}

def maybeUnwrapFieldType[A](fieldType: Type)(implicit tag: TypeTag[A]): Option[Type] = {
if (fieldType.typeConstructor == tag.tpe.typeConstructor) {
fieldType.typeArgs.headOption
} else {
Option(fieldType)
}
}

def getFieldClass(className: String, fieldName: String): java.lang.Class[_] = {

// case normal field return its class
// case Option field return generic type of Option

val result = for {
fieldType <- getFieldType(className, fieldName)
unwrappedFieldType <- maybeUnwrapFieldType[Option[_]](fieldType)
} yield {
mirror.runtimeClass(unwrappedFieldType)
}

// Consider changing return type to: Option[Class[_]]
result.getOrElse(null)
}
}

然后:

ReflectionHelper.getFieldClass("myapp.model.Person", "age")  // int
ReflectionHelper.getFieldClass("myapp.model.Person", "name") // class java.lang.String

我建议将 getFieldClass 的返回类型更改为可选的,以防字段值没有意义!

关于java - 如何在 Scala 运行时获取泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37011958/

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