Scala中的动态(向下)转换

时间:2013-12-12 15:25:27

标签: arrays scala types casting

我目前正试图弄清楚Scala的类型系统和Scala反射的深度。 我有以下示例代码(我的实际代码更复杂,更有意义,但归结为此):

abstract class Node
class Foo extends Node
case class ArrayFoo(var subs : Array[Foo]) extends Foo
case class IntFoo(i : Integer) extends Foo

object Main {
  def DoSomething(node : AnyRef) : AnyRef = { // Fix this function?
    // do some stuff
    node
  }

  def SetArrayWithReflection(n : Node, a : AnyRef) = {
    if (a.isInstanceOf[Array[AnyRef]]) {
      val arrayA = a.asInstanceOf[Array[AnyRef]].map(f => DoSomething(f)) // FIX this call?
      val getter = n.getClass.getMethods.find(p => p.getName == "subs")
      val setter = n.getClass.getMethods.find(p => p.getName == "subs_$eq")
      if (setter == None) println("Method not found!") else {
        println(f"would need to downcast from ${arrayA.getClass.getComponentType} to ${getter.get.getReturnType.getComponentType}")
        setter.get.invoke(n, arrayA) // Error happens here
      }
    }
  }

  def main(args : Array[String]) : Unit = {
    val my = ArrayFoo(Array(IntFoo(1), IntFoo(2), IntFoo(3)))
    val newArray = Array(IntFoo(10), IntFoo(20), IntFoo(30))
    SetArrayWithReflection(my, newArray)
    my.subs.foreach(f => println(f))
  }
}

我得到的输出是:

would need to downcast from class java.lang.Object to class Foo
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at Main$.SetArrayWithReflection(Main.scala:19)
    at Main$.main(Main.scala:27)
    at Main.main(Main.scala)

通过反射,我尝试调用一个期望带有Array [Foo]的Array [Object]的方法,这显然必须失败。 我的问题是:我如何向下转换或为方法调用创建合适的数组? 但是,相同的代码适用于列表。我想这是因为类型擦除不会在阵列上发生。

提前致谢,

韦利内

1 个答案:

答案 0 :(得分:1)

您无法将Array[Object]转发给Array[Foo]。创建所需数组的最简单方法是

val arrayFoo = Array.ofDim[Foo](arrayA.length)
System.arraycopy(arrayA, 0, arrayFoo, 0, arrayA.length)

请参阅System.arraycopy