输入参数化和奇怪的强制转换异常

时间:2015-09-25 17:55:27

标签: scala type-parameter

我有以下代码,它在满足谓词let paramString:NSMutableString = NSMutableString(); (obj as! NSArray).enumerateObjectsUsingBlock({ (object, idx, stop) -> Void in if ((object.isKindOfClass(NSDictionary)) != nil){ let pair:NSDictionary? = object as? NSDictionary; let textId:NSNumber? = pair?.objectForKey("TextId") as? NSNumber; var content:NSString? = pair?.objectForKey("Content") as? NSString; if ((content == nil) || (content?.length == 0) ) { content = " "; } if ((textId != nil) && (content != nil)) { paramString.appendFormat("%ld:%@\n", textId!.integerValue, content!); } } }); 的任何元素之前将数组拆分为数组数组。它键入检查:

p

当我用非空def splitBefore[T](a: Array[T], p: (T) => Boolean) (implicit tct: ClassTag[T]): Array[Array[T]] = a.foldLeft(Array[Array[T]](Array.empty[T])) { (acc: Array[Array[T]], s: T) => if (p(s)) acc :+ Array(s) else acc.init :+ (acc.last :+ s) }

调用它时,它工作正常
a

但是当我用一个空数组调用它时,我得到一个scala> splitBefore(Array("a", "BC", "d"), (s: String) => s.size > 1) res1: Array[Array[String]] = Array(Array(a), Array(BC, d))

ClassCastException

当我手动内联调用以便没有类型参数化时,它可以正常工作:

scala> splitBefore(Array.empty[String], (s: String) => s.size > 1)
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[Ljava.lang.String;
  ... 33 elided

知道这里发生了什么吗?我正在使用Scala 2.11.7。

1 个答案:

答案 0 :(得分:2)

看起来像实例化嵌套数组会导致错误 - 即使在这么小的例子上它也会崩溃:

def instantiate[A](ununsed_arg: Array[T])(implicit tag: ClassTag[A]) =
  Array[Array[A]](Array.empty[A])

作为一种快速解决方法,您可以使用ArrayBuilder创建一个数组:

def instantiate[T](a: Array[T])(implicit ctc: ClassTag[T]) = {
  val builder = ArrayBuilder.make[Array[T]]
  builder += Array.empty[T]
  builder.result
}

另请注意,您的代码段会直接将元素附加到数组中,这是一个坏主意,因为它必须创建一个包含多个插槽的新数组并复制元素。看起来您应该使用ArrayBuilderArrayBuffer进行处理,或者从列表中构建新的数据结构,并在结尾处将其转换为Arrays