首页 > 解决方案 > 在运行时在 Scala 中获取泛型参数的显式类型

问题描述

注意 - 这篇文章引用了 Spark,但不一定需要 - 它可以应用于任何需要类型参数的东西,(例如case class MyThing[T](t:T)

我正在尝试确定什么是通用参数的运行时类,特别是在数据集中,为了了解有用的错误消息,我正在尝试执行以下操作:

def killIfEmpty[T](ds:Dataset[T])(implicit sparkSession:SparkSession):Unit = {
if (ds.head(1).isEmpty) {
  throw new Exception(s"Dataset[${
    ds.getClass.getSimpleName
  }] had zero rows.")
}

}

但不幸的是,这并没有显示任何有用的信息,调用

val spark:SparkSession = ???
val emptyDs:Dataset[String] = ???
killIfEmpty[Dataset[String]](emptyDs)

我希望这会打印一条消息,上面写着:

Dataset[String] 有零行。

但是会发生什么结果:

Dataset[Dataset] 有零行。

有谁知道如何从泛型参数中获取实际的类名?

标签: scala

解决方案


知道了,我需要合作TypeTag

import scala.reflect.runtime.universe._

def killIfEmpty[T : TypeTag](ds:Dataset[T])(implicit sparkSession:SparkSession):Unit = {
    if (ds.head(1).isEmpty) {
      throw new Exception(s"Dataset[${
        datasetBaseClassName(typeTag[T])
      }] had zero rows.")
    }
  }

  private def datasetBaseClassName[T : TypeTag]: String = {
    typeOf[T].typeSymbol.name.toString
  }

提供绑定[T : TypeTag]在方法声明上的上下文允许我调用这些函数而无需显式提供标记。请参阅有关上下文边界的文档以了解更多信息。

我认为有一种方法可以做到这一点,而无需定义与公开可用killIfEmpty功能绑定的相同上下文,但我不确定 - 我愿意更正!


推荐阅读