Scala FAQ: How can I pass an array back and forth between Scala and Java code?
Solution
The first link in the See Also section states, “Scala arrays correspond one-to-one to Java arrays,” and as a result of this, passing arrays back and forth between Java and Scala code is easier than the example shown in Recipe 17.1 in the Scala Cookbook, “Going to and from Java Collections.”
For instance, if you have a Java class with methods that return an int[]
or String[]
, like these:
// java package javaarrays; public class Test { public static int[] getNumbers() { int[] x = {1, 2, 3}; return x; } public static String[] getStrings() { String[] x = {"a", "b", "c"}; return x; } }
you can call them directly from your Scala application:
package javaarrays object ArrayTest extends App { Test.getNumbers.foreach(println) Test.getStrings.foreach(println) }
If you look at the types in your Scala code, you can see how Scala sees them:
println(Test.getNumbers.getCanonicalName) // int[] println(Test.getStrings.getClass.getCanonicalName) // String[]
You can also access a Scala Array
from a Java application. Given this Scala code that builds a method named getFriends
:
package javaarrays object ArrayTest { // create one Person val fred = Person("Fred") val fredsFriends = Array(Person("Barney"), Person("Betty"), Person("Wilma")) fred.friends = fredsFriends // create a second Person val barney = Person("Barney") val barneysFriends = Array(Person("Betty"), Person("Fred"), Person("Wilma")) barney.friends = barneysFriends // return the two Person instances when called def getFriends = Array(fred, barney) } case class Person(name: String) { var friends = Array[Person]() override def toString = s"$name (${friends.mkString(",")})" }
you can use the following Java class to call the getPerson
method and print out the Person
instances:
package javaarrays; public class GetScalaArrays { public static void main(String[] args) { Person[] peeps = ArrayTest.getFriends(); for (Person p: peeps) { System.out.println(p); } } }
As long as you’re working with an Array
on the Scala side and treating it as an array of objects in Java, this works fine.
Discussion
In the book, Programming in Scala, the authors discuss an unusual situation that can happen with legacy Java code. One approach to having an array of objects in Java where each object was a subtype of some supertype was to define the array as Object[]
. This is shown in the following Java code, where the method printObjectArray
expects an array of Object
:
// java package javaarrays2; public class AJavaClass { public static void printObjectArray(Object[] objects) { for (Object o: objects) { System.out.println(o); } } }
Attempting to call this Java method from Scala with an array of type Any
will not work:
val objects = Array("a", 1) AJavaClass.printObjectArray(objects) // will not compile
For that matter, an array of String
also won’t work:
val objects = Array("a", "b") AJavaClass.printObjectArray(objects) // will not compile
The solution to this problem is to cast your Scala array to an Array[Object]
, as shown here:
// this works val objects = Array("a", 1) val arrayOfObject = objects.asInstanceOf[Array[Object]] AJavaClass.printObjectArray(arrayOfObject)
See Also
- A discussion of the
Array
class, including how it’s a “special kind of collection”: http://www.scala-lang.org/docu/files/collections-api/collections_38.html - Recipe 17.1 in the Scala Cookbook, “Going to and from Java Collections,” discusses how to convert many types of collections when interacting with Java code
The Scala Cookbook
This tutorial is sponsored by the Scala Cookbook, which I wrote, and was published by O’Reilly in late 2013:
You can find the Scala Cookbook at these locations:
I hope it has been helpful. All the best, Al.