gpt4 book ai didi

Scala 2.10 反射 : Creating an Array from a type

转载 作者:行者123 更新时间:2023-12-01 11:46:46 25 4
gpt4 key购买 nike

我在浏览有关新 2.10 版本的 Scala(有点稀疏?)文档时遇到了问题。我有一种情况,我正在从没有类型信息的源中递归读取数据。在阅读时我知道预期的类型,因此我可以检查该类型是否与传入数据一致。

我的问题是:当尝试检索具有类型参数(例如 Array[Int])的集合对象时,我如何使用预期的类型来确保读取的值是正确的类型?

到目前为止,我一直在摆弄 Scala Api 提供的代码允许您提取类型参数。我还读到了 Class Tags以及如何使用它们来创建数组。所以我的下一个想法是 1) 找到类型参数,2) 从该类型创建一个数组,以及 3) 查看读取的数据是否无一异常(exception)地适合,如下所示:

val paramType = paramInfo[Array[X]]  // Step 1: Find the X type parameter
val array = Array[paramType](size) // Step 2: Can't use TypeTags#Type as a normal Java type...
// Step 3: Feed data into the array and hope for the best
// Step 4: Profit!

既然上面的 paramType 给了我类型,那么将该类型转换为类标签应该是一件简单的事情。但答案让我迷惑了。

老实说,这个解决方案对我来说似乎有点困惑,但我还没有想出更聪明的办法。如果有其他解决方案,我会洗耳恭听!

提前致谢。

编辑:为了澄清,我上面的例子应该证明我想从 Array[Int] 中提取类型 X(例如),然后创建一个包含该特定类型的数组的实例。希望这能让它更清楚。

编辑:也许需要进一步澄清(我真的说得那么不清楚吗?:-))。我想从数据源读取一个集合。我希望该集合以正确的、预期的类型输入。假设我调用方法 readData。因为我知道期望的类型,所以我给它一个期望类型的类型参数。例如,假设 Array[Int]。它可以是 Array[String] 或 Iterable[Any] 或只是 Null 或其他。当调用 readData 方法时,我想将给定的预期类型 (Array[Int]) 与从外部源读取的数据类型相匹配。如果找到的类型与我们预期的类型是同一类型(或子类型),则可以强制转换并返回数据。如果不是,则抛出异常,通知用户找到的数据不是预期的类型。总结一下:如何调用 readData[Array[Int]] 工作?

编辑:我通过创建数组 [Any] 解决了这个问题,检索预期类型(上面的 X)并迭代数组以查看元素是否属于 X 的相同类型(或子类型)。如果是,我们可以安全地转换为 Array[X]。在下面的示例中,预期的类型由 E 表示。我知道这很老套,但还是要重申:我希望看到替代方案...

// Matches if the type of o corresponds (<:<) to the type of x
def verifyType(o : Any, x : Type) : Boolean = { ... }

// Get the type of the array parameter (X)
val tpe = reflect.runtime.universe.typeOf[E] tpe match {
// The returned Type is not an instance of universe.Type - hence the cast
case TypeRef(_, _, args) => args.asInstanceOf[List[Type]]
case _ => throw new IllegalArgumentException("Could not find type parameters in type " + tpe)
}

// Iterate the array and make sure the types match
val hasWrongType = array.exists(e => !verifyType(e, tpe))

if (hasWrongType) throw new Exception(...) // The types does not fit
else array.asInstanceOf[E] // We can safely cast

最佳答案

您实际上不需要 Scala 2.10 中的任何新内容来执行此操作,尽管您使用替代品 ClassTag 而不是早期版本的 ClassManifest:

def makeArray[T : reflect.ClassTag](length: Int): Array[T] = {
val tTag = implicitly[reflect.ClassTag[T]]
tTag.newArray(length)
}

在 REPL 中:

scala> makeArray[String](5)
res0: Array[String] = Array(null, null, null, null, null)

使用原始类型:

scala> makeArray[Int](5)
res1: Array[Int] = Array(0, 0, 0, 0, 0)

编辑:取两个:

def makeArrayLike(a: Array[_], length: Int): Array[_] = {
val cA = a.getClass
val cC = cA.getComponentType
java.lang.reflect.Array.newInstance(cC, length).asInstanceOf[Array[_]]
}

在 REPL 中:

scala> val ai1 = Array[Int](1, 2, 3)
ai1: Array[Int] = Array(1, 2, 3)

scala> val as1 = Array[String]("one", "two", "three")
as1: Array[String] = Array(one, two, three)

scala> makeArrayLike(as1, 5)
res0: Array[_] = Array(null, null, null, null, null)

scala> makeArrayLike(ai1, 5)
res1: Array[_] = Array(0, 0, 0, 0, 0)

关于Scala 2.10 反射 : Creating an Array from a type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14638143/

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