I'm trying to call my Scala Util
object from Java code:
Main.java
Set<Long> items = new HashSet<Long>();
// fill up items with Long
MyUtil.foo(100, items);
Util.scala
object Foo {
type Id = Long
def foo(id: Id, items: scala.collection.mutable.Set[Id])
Here's the compile-time error:
could not parse error message:
required: long,scala.collection.mutable.Set<Object>
found: Long,java.util.Set<Long>
reason: actual argument java.util.Set<Long> cannot be converted to
scala.collection.mutable.Set<Object> by method invocation conversion`
From reading these Java to Scala Collections docs, I am using a mutable
Set rather than the default, immutable Set:
scala.collection.mutable.Set <=> java.util.Set
But, I don't understand the error message. By using a Long
(boxed long
) in my Java code, why is a Set<Long>
found?
Demonstrating what the commenter said:
scala> import collection.JavaConverters._
import collection.JavaConverters._
scala> val js = (1 to 10).toSet.asJava
js: java.util.Set[Int] = [5, 10, 1, 6, 9, 2, 7, 3, 8, 4]
scala> def f(is: collection.mutable.Set[Int]) = is.size
f: (is: scala.collection.mutable.Set[Int])Int
scala> def g(js: java.util.Set[Int]) = f(js.asScala)
g: (js: java.util.Set[Int])Int
scala> g(js)
res0: Int = 10
Working with Scala collections and type aliases from Java code (not the converse, as som-snytt showed :) is going to be at least nasty, most likely very painful, and quite possibly impossible.
If you're able to modify the Scala side of the API, I'd recommend adding a Java-friendlier API to it. If not, I guess you could build an adapter layer in Scala that proxies Java clients through to the native Scala API.
So, something like:
// Original Scala
object Foo {
type Id = Long
def foo(id: Id, items: scala.collection.mutable.Set[Id])
}
// Java adapter -- generics might be made to work on the Java side,
// but Long is particularly problematic, so we'll just force it here
object FooJ {
import scala.collection.JavaConverters._
def foo(id: Long, items: java.util.Set[Long]) = {
Foo.foo(id, items.asScala)
}
}