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)