首页 > 解决方案 > 确定 Scala 类中 Option 字段的类型

问题描述

问题

你如何确定一个类的每个字段的类型?

给定以下案例类:

case class GenericCaseClass(
    a: Boolean,
    b: Byte,
    c: Short,
    d: Int,
    e: Long,
    f: Float,
    g: Double,
    h: Char,
    i: String,
    j: Option[Boolean],
    k: Option[Byte],
    l: Option[Short],
    m: Option[Int],
    n: Option[Long],
    o: Option[Float],
    p: Option[Double],
    q: Option[Char],
    r: Option[String]
)

初步尝试

import java.lang.reflect.{Field, ParameterizedType}

def printType(field: Field): Unit = {
    val scalaClass = field.getType

    if (scalaClass == classOf[Boolean]) {
        println("Boolean")
    } else if (scalaClass == classOf[Byte]) {
        println("Byte")
    }
    ...
    } else if (scalaClass == classOf[Option[Boolean]]) {
        println("Boolean")
    } else if (scalaClass == classOf[Option[Byte]]) {
        println("Byte")
    }
    ...
}

classOf[GenericCaseClass].getDeclaredFields.foreach(
    declaredField => {
        printType(declaredField)
    }
)

初步结果

当前尝试

我在 if 语句链的开头添加了以下内容,以尝试获取选项的内部类型:

if (scalaClass == classOf[Option[_]]) {
    val innerType = field
        .getGenericType
        .asInstanceOf[ParameterizedType]
        .getActualTypeArguments
        .head
        .getTypeName

    println("Option[_] -> " + innerType)
}

但它似乎只适用于字符串:

注意:我使用的是 Scala 版本 2.11.11。

标签: scalareflection

解决方案


使用 Java 反射很快让我头疼,所以这里有一个非常简单的 Scala 解决方案:

import scala.reflect.runtime.universe._

//--Your case class definition--//

val values = typeOf[GenericCaseClass].members.filterNot(_.isMethod)

def prettyPrintField(symbol: Symbol): Unit = {
  val name = symbol.name
  val typeSignature: Type = symbol.typeSignature
  println(s"$name: $typeSignature")
}

values.foreach(prettyPrintField)

输出:

r : Option[String]
q : Option[Char]
<- rest of fields ->
a : Boolean

推荐阅读