【发布时间】:2020-01-10 08:15:29
【问题描述】:
在这篇文章中:
Is it possible to convert a TypeTag to a Manifest?
表明可以使用以下代码将TypeTag转换为Manifest:
def toManifest[T:TypeTag]: Manifest[T] = {
val t = typeTag[T]
val mirror = t.mirror
def toManifestRec(t: Type): Manifest[_] = {
val clazz = ClassTag[T](mirror.runtimeClass(t)).runtimeClass
if (t.typeArgs.length == 1) {
val arg = toManifestRec(t.typeArgs.head)
ManifestFactory.classType(clazz, arg)
} else if (t.typeArgs.length > 1) {
val args = t.typeArgs.map(x => toManifestRec(x))
ManifestFactory.classType(clazz, args.head, args.tail: _*)
} else {
ManifestFactory.classType(clazz)
}
}
toManifestRec(t.tpe).asInstanceOf[Manifest[T]]
}
不起作用,如以下测试用例所示:
object TypeTag2Manifest {
class Example {
type T = Map[String, Int]
}
val example = new Example
}
class TypeTag2Manifest extends FunSpec {
import org.apache.spark.sql.catalyst.ScalaReflection.universe._
import TypeTag2Manifest._
it("can convert") {
val t1 = implicitly[TypeTag[example.T]]
val v1 = toManifest(t1)
val v2 = implicitly[Manifest[example.T]]
assert(v1 == v2)
}
}
输出:
scala.collection.immutable.Map did not equal scala.collection.immutable.Map[java.lang.String, Int]
ScalaTestFailureLocation: com.tribbloids.spike.scala_spike.reflection.TypeTag2Manifest at (TypeTag2Manifest.scala:52)
Expected :scala.collection.immutable.Map[java.lang.String, Int]
Actual :scala.collection.immutable.Map
显然,这表明类型擦除一直困扰着转换,并且 TypeTag 尽管被设计为避免类型擦除,但只能解析为依赖类型 example.T 而无法从基础类型 Map[String, Int] 中获取正确的类型参数。
那么有什么方法可以将 TypeTag 和 Manifest 互相转换成不烂的呢?
【问题讨论】:
标签: scala type-erasure scala-reflect