gpt4 book ai didi

scala - 在 Scala 中,如何从可序列化的类型创建 TypeTag?

转载 作者:行者123 更新时间:2023-12-03 03:43:59 28 4
gpt4 key购买 nike

在 Scala 反射中,通常可以使用 TypeCreator 从类型构造 TypeTag:

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 不同,它是不可序列化的:

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 不可序列化,而第一个 TypeTag 可以序列化。

所以我的问题是:如何使第二个 TypeTag 像第一个 TypeTag 一样可序列化?

我现在使用的是 scala 2.12.10。

最佳答案

基于How to create a TypeTag manually?

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 - 在 Scala 中,如何从可序列化的类型创建 TypeTag?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59450274/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com