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
?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With