在Scala反射中,通常可以使用TypeCreator从Type构造TypeTag:
In Scala reflection, the TypeTag can usually be constructed from a Type using a TypeCreator:
object TypeUtils { import ScalaReflection.universe._ def createTypeTag[T]( tpe: Type, mirror: reflect.api.Mirror[reflect.runtime.universe.type] ): TypeTag[T] = { TypeTag.apply( mirror, NaiveTypeCreator(tpe) ) } case class NaiveTypeCreator(tpe: Type) extends reflect.api.TypeCreator { def apply[U <: reflect.api.Universe with Singleton]( m: reflect.api.Mirror[U]): U#Type = { // assert(m eq mirror, s"TypeTag[$tpe] defined in $mirror cannot be migrated to $m.") tpe.asInstanceOf[U#Type] } }不幸的是,事实证明createTypeTag的输出不可序列化,这与通过编译时推断创建的typeTag不同:
Unfortunately, it turns out the output of createTypeTag is not serializable, unlike the typeTag created from compile-time inference:
import java.io.{ByteArrayOutputStream, ObjectOutputStream} import org.apache.spark.sql.catalyst.ScalaReflection import org.scalatest.FunSpec class TypeTagFromType extends FunSpec { import ScalaReflection.universe._ it("create TypeTag from reflection") { val ttg = typeTag[String] val ttg2 = TypeUtils.createTypeTag(ttg.tpe, ttg.mirror) Seq( ttg -> "from static inference", ttg2 -> "from dynamic type" ).foreach { case (tt, k) => println(k) val bos = new ByteArrayOutputStream() try { val out = new ObjectOutputStream(bos) out.writeObject(tt) out.flush() val array = bos.toByteArray } finally { bos.close() } } } }这给出了输出:
from static inference from dynamic type scala.reflect.runtime.JavaMirrors$JavaMirror$$anon$2 java.io.NotSerializableException: scala.reflect.runtime.JavaMirrors$JavaMirror$$anon$2 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)表示第二个TypeTag是不可序列化的,而第一个是不可序列化的.
Indicating that the second TypeTag is not serializable, while the first one is.
所以我的问题是:如何使第二个TypeTag像第一个一样可序列化?
So my question is: how to make the second TypeTag to be serializable like the first one?
此刻我正在使用Scala 2.12.10.
I'm using scala 2.12.10 at the moment.
推荐答案基于如何手动创建TypeTag?
如果您需要可序列化的TypeTag并且性能不是您的主要任务 关注
if you need a serializable TypeTag and performance isn't your main concern
然后考虑
import scala.reflect.runtime.universe._ import scala.reflect.runtime.currentMirror import scala.tools.reflect.ToolBox def createTypeTag(tp: Type): TypeTag[_] = { val toolbox = universe.runtimeMirror(getClass.getClassLoader).mkToolBox() val ttree = toolbox.parse(s"scala.reflect.runtime.universe.typeTag[$tp]") toolbox.eval(ttree).asInstanceOf[TypeTag[_]] } val ttg = typeTag[List[String]] val ttg2 = createTypeTag(ttg.tpe) ...更多推荐
在Scala中,如何从可序列化的类型创建TypeTag?
发布评论