确定Scala类中Option字段的类型

时间:2018-07-23 19:26:20

标签: scala reflection

问题

您如何确定课程每个字段的类型?

给出以下案例类:

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

初始结果

  • 布尔值
  • 字节
  • Int
  • 浮动
  • Double
  • Char
  • 字符串
  • 选项[布尔]
  • 选项[布尔]
  • 选项[布尔]
  • 选项[布尔]
  • 选项[布尔]
  • 选项[布尔]
  • 选项[布尔]
  • 选项[布尔]
  • 选项[布尔]

当前尝试

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

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

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

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

  • 布尔值
  • 字节
  • Int
  • 浮动
  • Double
  • Char
  • 字符串
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.Object
  • 选项[_]-> java.lang.String

注意:我正在使用Scala 2.11.11版。

2 个答案:

答案 0 :(得分:2)

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

string.toLowerCase

输出:

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)

答案 1 :(得分:0)

使用ClassTag访问运行时类型信息:

import scala.reflect.ClassTag
def getOptionType[T](opt: Option[T])(implicit t: ClassTag[T]) = t.runtimeClass