使用Scala反射从对象获取基元字段的类型

使用Scala反射从对象获取基元字段的类型,scala,reflection,scala-reflect,Scala,Reflection,Scala Reflect,因此,我试图获取Scala对象类中每个字段的类型: package myapp.model object MyObject { val theInt: Option[Int] } 使用Brian在中提供的ReflectionHelper。我使用getFieldType,但它返回的是Option[Object],而不是它是什么,即Option[Int]。该答案中的示例代码适用于案例类,例如: package myapp.model case class Person( name: St

因此,我试图获取Scala对象类中每个字段的类型:

package myapp.model

object MyObject {
  val theInt: Option[Int]
}
使用Brian在中提供的ReflectionHelper。我使用
getFieldType
,但它返回的是
Option[Object]
,而不是它是什么,即
Option[Int]
。该答案中的示例代码适用于案例类,例如:

package myapp.model

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

scala> ReflectionHelper.getFieldType("myapp.model.Person", "age")  // int
res12: Option[reflect.runtime.universe.Type] = Some(Option[Int])
但是,如果我在Scala对象字段上运行
getFieldType
,我们会得到以下结果:

scala> ReflectionHelper.getFieldType("myapp.model.MyObject$", "theInt")
res10: Option[reflect.runtime.universe.Type] = Some(Option[Object])
导致这种行为的Scala对象有什么不同?我如何让
getFieldType
返回
Option[Int]
而不是像case类那样返回
Option[Object]

为方便起见,下面是另一个问题的ReflectionHelper:

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)
  }
}
import scala.reflect.runtime.{universe=>u}
导入scala.reflect.runtime.universe_
对象反射辅助对象{
val classLoader=Thread.currentThread().getContextClassLoader
val mirror=u.runtimeMirror(类加载器)
def getFieldType(类名:String,字段名:String):选项[Type]={
val classSymbol=mirror.staticClass(类名)
为了{
字段符号
})
}屈服{
fieldSymbol.info.resultType
}
}
def maybeUnwrapFieldType[A](字段类型:类型)(隐式标记:类型标记[A]):选项[Type]={
if(fieldType.typeConstructor==tag.tpe.typeConstructor){
fieldType.typeArgs.headOption
}否则{
选项(字段类型)
}
}
def getFieldClass(类名:String,字段名:String):java.lang.Class[\uz]={
//case normal字段返回其类
//案例选项字段返回选项的通用类型
val结果=用于{
fieldTypeTry

// import scala.reflect.runtime.universe._  
mirror.staticClass("myapp.model.Person").typeSignature.member(TermName("age")).typeSignature // => Option[Int]    
mirror.staticModule("myapp.model.MyObject").typeSignature.member(TermName("theInt")).typeSignature // => Option[Int]