Scala 为什么数组需要类清单而不是列表?

Scala 为什么数组需要类清单而不是列表?,scala,scala-2.8,scala-collections,Scala,Scala 2.8,Scala Collections,定义以下代码: import scala.collection.JavaConversions._ val iter:java.util.Iterator[Any] = Array[Any](1, 2, 3).iterator def func(a:Any):String = a.toString def test[T:ClassManifest](iter:java.util.Iterator[Any], func:Any=>T):Array[T] = iter.map(i

定义以下代码:

import scala.collection.JavaConversions._  
val iter:java.util.Iterator[Any] = Array[Any](1, 2, 3).iterator
def func(a:Any):String = a.toString

def test[T:ClassManifest](iter:java.util.Iterator[Any], func:Any=>T):Array[T] =  
  iter.map(i=>func(i)).toArray

def testFunc = test(iter, func)
在这里,我需要使用
ClassManifest
来正确编译它,否则会出现错误:

scala> def test[T](iter:java.util.Iterator[Any], func:Any=>T):Array[T] = 
     |   iter.map(i=>func(i)).toArray         

<console>:11: error: could not find implicit value for evidence parameter of 
type ClassManifest[T]
     iter.map(i=>func(i)).toArray
                          ^
请注意,
testFunc
testFunc1
的最终输出是相同的


为什么
列表
版本不需要
类清单

简单的回答是因为这些方法就是这样的:

如果您在代码中取消了
def test[T:ClassManifest]
中的
:ClassManifest
,那么编译器所知道的就是它有一些未知类型
T
,因此编译器无法找到该类型的
ClassManifest

为什么代码需要
类清单
?如果你看到:

val result = new Array[B](size)
数组的这个构造函数需要一个
类清单
。请参阅Easy Angel的答案以获取此文档。以下是一个在REPL中演示的示例:

scala> def createArray[T] = new Array[T](10)
<console>:5: error: cannot find class manifest for element type T
       def createArray[T] = new Array[T](10)
scala>def createArray[T]=新数组[T](10)
:5:错误:找不到元素类型T的类清单
def createArray[T]=新数组[T](10)

因此,基本上,您必须编写
T:ClassManifest
,因为Scala需要
ClassManifest
来创建新数组。

方法
toArray
使用
T
类型的元素创建新数组。以及:

因此,根据T的实际类型参数,它可以是数组[Int],或数组[Boolean],或Java中其他一些基本类型的数组,或某个引用类型的数组。但是这些类型都有不同的运行时表示,那么Scala运行时如何选择正确的表示呢?事实上,它不能基于所提供的信息来实现这一点,因为与类型参数t对应的实际类型在运行时被擦除


Scala使用JVM本机数组作为
数组
的实现。只有使用已知类型才能创建此类文件

由于Sun决定创建遗留工件,泛型类型被擦除,不再以字节码的形式出现。这意味着在运行时,
Array[T]
不再知道
T
的值,因此VM无法创建数组。当您尝试兼容Java1.4并在数组上引入泛型时,您会遇到一些更复杂的陷阱(我也不了解整个深度),但底线是:JVM/Java的数组不是泛型的;Scala帮助我们进行一般抽象


因此,您提到的类清单本质上是一个黑客。它静态地确保在通过请求此隐式参数来创建数组时,类型信息可用。实际上,任何创建类型参数数组的方法/函数都必须要求隐式清单,其所有被调用方等直到类型已知为止(静态)。

Java中的数组不会被类型擦除,尤其是
数组[Int]
不同于
数组[Object]
在JVM级别


对于任何其他类,类型参数都会被擦除到
Object
,因此
List[Int]
List[Object]
在JVM级别具有相同的表示形式。

“大概是因为对象实际上是按顺序放在堆上的”不,它们不是。对象数组按顺序存储引用,而不是对象本身。(当然,这不适用于原语数组。)您和Angel的答案结合在一起形成了正确的答案:)
val result = new Array[B](size)
scala> def createArray[T] = new Array[T](10)
<console>:5: error: cannot find class manifest for element type T
       def createArray[T] = new Array[T](10)