在Java中使用`Set`参数到Scala代码

时间:2014-01-30 20:42:12

标签: java scala

我正在尝试从Java代码中调用我的Scala Util对象:

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]) 

这是编译时错误:

  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`

从阅读这些Java到Scala Collections docs,我使用的是mutable Set,而不是默认的,不可变的Set:

scala.collection.mutable.Set <=> java.util.Set

但是,我不明白错误信息。在我的Java代码中使用Long(盒装long),为什么找到了Set<Long>

2 个答案:

答案 0 :(得分:2)

证明评论者所说的话:

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

答案 1 :(得分:1)

使用 Scala集合并从 Java代码中键入别名(而不是相反的,因为som-snytt显示:)将至少是令人讨厌的,大多数可能非常痛苦,而且很可能是不可能的。

如果您能够修改API的Scala端,我建议为其添加一个Java友好的API。如果没有,我猜你可以在Scala中构建一个适配器层,将Java客户端代理到本机Scala API。

所以,比如:

// 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)
  }
}