Java 如何从Scala中的泛型类型获取字段名和字段类型?

Java 如何从Scala中的泛型类型获取字段名和字段类型?,java,scala,generics,reflection,scala-reflect,Java,Scala,Generics,Reflection,Scala Reflect,在Scala中,给定泛型类型T,如何检索字段名列表和字段类型?例如,如果我有case类: case class Person(name: String, age: Int, gender: Boolean) 以及泛型函数: def getFieldNamesAndTypes[T](): Seq[(String, String)] 我希望能够检索字段(名称、类型)的序列(以便字段显示): 您似乎需要反射API: Welcome to Scala 2.13.1 (OpenJDK 64-Bit S

在Scala中,给定泛型类型T,如何检索字段名列表和字段类型?例如,如果我有case类:

case class Person(name: String, age: Int, gender: Boolean)
以及泛型函数:

def getFieldNamesAndTypes[T](): Seq[(String, String)]
我希望能够检索字段(名称、类型)的序列(以便字段显示):


您似乎需要反射API:

Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 1.8.0_222).
Type in expressions for evaluation. Or try :help.

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

scala> def getFields[T: TypeTag] = typeOf[T].members.collect {
     |   case m: MethodSymbol if m.isCaseAccessor => (m.name.toString, m.returnType.toString)
     | }
getFields: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])Iterable[(String, String)]

scala> case class Person(name: String, age: Int, gender: Boolean)
defined class Person

scala> getFields[Person]
res0: Iterable[(String, String)] = List((gender,Boolean), (age,Int), (name,String))

您甚至可以在编译时使用Shapeless(即在引擎盖下使用编译时反射)执行此操作

导入shapeless.labeled.FieldType
导入shapeless.ops.hlist.{FillWith,Mapper,ToList}
导入无形状。{HList,LabelledGeneric,Poly0,Poly1,可键入,见证}
对象fieldTypePoly扩展了Poly1{
隐式def cse[K witness.value.name->typeable.descripe)
}
对象nullPoly扩展了Poly0{
隐式def cse[A]:Case0[A]=at(null.asInstanceOf[A])
}
def getFieldNamesAndTypes[T]=新的部分应用[T]
类部分应用[T]{

def apply[L看起来像X/Y。您认为获取此类信息是实现解决方案的一种方式(以及哪种解决方案)的目标是什么?顺便说一句,运行时反射只应在边缘情况下考虑,因为它会破坏所有类型安全。我看到一些关于类和类型信息的问题,您最近发布了。我建议您学习Shapess/magnolia库。您的所有问题都将被涵盖。
Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 1.8.0_222).
Type in expressions for evaluation. Or try :help.

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

scala> def getFields[T: TypeTag] = typeOf[T].members.collect {
     |   case m: MethodSymbol if m.isCaseAccessor => (m.name.toString, m.returnType.toString)
     | }
getFields: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])Iterable[(String, String)]

scala> case class Person(name: String, age: Int, gender: Boolean)
defined class Person

scala> getFields[Person]
res0: Iterable[(String, String)] = List((gender,Boolean), (age,Int), (name,String))
import shapeless.labelled.FieldType
import shapeless.ops.hlist.{FillWith, Mapper, ToList}
import shapeless.{HList, LabelledGeneric, Poly0, Poly1, Typeable, Witness}

object fieldTypePoly extends Poly1 {
  implicit def cse[K <: Symbol, V](implicit
    witness: Witness.Aux[K],
    typeable: Typeable[V]
  ): Case.Aux[FieldType[K, V], (String, String)] =
    at(_ => witness.value.name -> typeable.describe)
}

object nullPoly extends Poly0 {
  implicit def cse[A]: Case0[A] = at(null.asInstanceOf[A])
}

def getFieldNamesAndTypes[T] = new PartiallyApplied[T]

class PartiallyApplied[T] {
  def apply[L <: HList, L1 <: HList]()(implicit
    generic: LabelledGeneric.Aux[T, L],
    mapper: Mapper.Aux[fieldTypePoly.type, L, L1],
    fillWith: FillWith[nullPoly.type, L],
    toList: ToList[L1, (String, String)]
  ): Seq[(String, String)] = toList(mapper(fillWith()))
}

case class Person(name: String, age: Int, gender: Boolean)

getFieldNamesAndTypes[Person]() // List((name,String), (age,Int), (gender,Boolean))