Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is ClassManifest needed with Array but not List?

Define the following code:

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)

Here, I need to use ClassManifest for it to compile correctly, otherwise I get the error:

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
                          ^

On the other hand, the alternate code below using List does not require this and compiles fine.

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

def test1[T](iter:java.util.Iterator[Any], func:Any=>T):List[T] = 
  iter.map(i=>func(i)).toList   


def testFunc1 = test1(iter, func).toArray

Note that the final output of testFunc and testFunc1 are identical.

How come the List version does not require a ClassManifest?

like image 266
Jus12 Avatar asked Jan 31 '11 12:01

Jus12


2 Answers

Arrays in Java are not type-erased, and, in particular, an Array[Int] is different than an Array[Object] at the JVM level.

For any other class, type parameters are erased to Object, so List[Int] and List[Object] have the same representation at the JVM level.

like image 53
Daniel C. Sobral Avatar answered Oct 20 '22 19:10

Daniel C. Sobral


Method toArray creates new array with elements of type T. And according to documentation:

So depending on the actual type parameter for T, this could be an Array[Int], or an Array[Boolean], or an array of some of the other primitive types in Java, or an array of some reference type. But these types have all different runtime representations, so how is the Scala runtime going to pick the correct one? In fact, it can't do that based on the information it is given, because the actual type that corresponds to the type parameter T is erased at runtime.

like image 40
tenshi Avatar answered Oct 20 '22 19:10

tenshi