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

时间:2020-08-07 09:24:56

标签: java scala generics reflection scala-reflect

在Scala中,给定通用类型T,如何检索字段名称和字段类型的列表?例如,如果我有案例类:

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

和通用函数:

def getFieldNamesAndTypes[T](): Seq[(String, String)]

我希望能够检索字段(名称,类型)的顺序(以显示字段的顺序):

val fieldNamesAndTypes = getFieldNamesAndTypes[Person]()

2 个答案:

答案 0 :(得分:4)

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

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))

答案 1 :(得分:3)

似乎您需要反射API:

path1