mdm
mdm

Reputation: 3988

Why does List<Object[]> needs explicit casting to convert into Scala collection?

Say I have the following Java collection:

public static List<Object[]> javaStuff = new ArrayList<Object[]>();

And that, from Scala, I want to refer to that collection, convert it Scala collection and return an Iterator[] over it.

Can anyone explain to me why the following (toy) code does not compile?

def convertMethod[Array[AnyRef]]() : Iterator[Array[AnyRef]] = {
   import scala.collection.JavaConverters._
   val r: mutable.Buffer[Array[AnyRef]] = MyTestClass.javaStuff.asScala // This does not compile!  
   r.iterator
}

More specifically, the error IntelliJ highlights is:
Expression of type Buffer[Array[AnyRef]] does not conform to expected type Buffer[Array[AnyRef]]

...which was quite uninformative. Trying to run the code, the error is a bit more helpful:

Error:(18, 58) type mismatch;
found   : scala.collection.mutable.Buffer[scala.Array[Object]]
required: scala.collection.mutable.Buffer[Array[AnyRef]]
   val r: mutable.Buffer[Array[AnyRef]] = MyTestClass.javaStuff.asScala
                                 ^

At which point, I changed the original code into:

def convertMethod[Array[AnyRef]]() : Iterator[Array[AnyRef]] = {
   import scala.collection.JavaConverters._
   val r: mutable.Buffer[Array[AnyRef]] = MyTestClass.javaStuff.asScala.map(_.asInstanceOf[Array[AnyRef]])
   r.iterator
 }

...and it worked!

Now my question really is: why is this necessary? Is there a way to avoid that explicit casting?

Upvotes: 1

Views: 739

Answers (2)

R&#233;gis Jean-Gilles
R&#233;gis Jean-Gilles

Reputation: 32739

The reason is simple. In convertMethod, Array is a type parameter and thus does not refer to scala.Array at all.

You should change this:

def convertMethod[Array[AnyRef]]()

to this:

def convertMethod()

Note that contrary to what shadowlands said in a comment, scala.Array really is the same thing as a java array (except for the fact that scala arrays are not covariant, but it does not come into play here).

Upvotes: 4

kiritsuku
kiritsuku

Reputation: 53358

Change

def convertMethod[Array[AnyRef]]() =

to

def convertMethod() =

The first one creates a method that takes a type parameter with name Array, which by itself takes a type parameter of name AnyRef (i.e. a higher kinded type). These newly introduced names hide the built in types Array and AnyRef.

Upvotes: 3

Related Questions