Scala用数组参数调用Java方法

时间:2017-02-02 08:24:35

标签: java scala

假设我有一个类似下面的Java API:

public class JavaApi<T> {
    public void foo(T[] data) {
        ...
    }
}

我想通过以下课程从Scala调用它:

class Caller[T] {
    val javaApi = new JavaApi[T]()

    def callApi(data: Array[T]) = javaApi.foo(data)
}

在编译时,我得到以下内容:

type mismatch;
found   : Array[T]
required: Array[T with Object]
Note: T >: T with Object, but class Array is invariant in type T.
You may with to investigate a wildcard type such as `_ >: T with Object`. (SLS 3.2.10)
  def callApi(data: Array[T]) = javaApi.foo(data)

2 个答案:

答案 0 :(得分:0)

您可以查看Scala type hierarchy。更具体地说:

  

如果在Java运行时环境的上下文中使用Scala,那么   scala.AnyRef对应于java.lang.Object

因此,通过更改它,Jubobs建议您确定该类型对应于一个对象:

class Caller[T<: AnyRef] {
    val javaApi = new JavaApi[T]()

    def callApi(data: Array[T]) = javaApi.foo(data)
}

因此,如果您需要任何值类型,如int,char,boolean,则需要将它们转换为对象等效的盒装Java类型,如Integer,Character或Boolean。看到: enter image description here

答案 1 :(得分:0)

这是由 Java 不支持primitive type的多态性引起的。

虽然 Scala 将任何内容视为对象,但在编译器编译之后,可能会将对象转换为基本类型数组用于提高性能,例如:

scala> var a = Array(1, 2, 3)
a: Array[Int] = Array(1, 2, 3)
scala> :javap -c a
public class $line3.$read$$iw$$iw$ {
  ...
  public int[] a();
  ...

如您所见,上述Array[Int]已转换为int[] 基本类型数组

因此,这可能导致 Java 方法不兼容。

解决方案:

  1. 正如@Jubobs所说,将T绑定到T <: AnyRef。如val a = Array[Integer](1, 2, 3),编译器将其作为Integer[]类型处理。
  2. 使用List替换ArrayList始终reference类型。
  3. 参考:

    https://issues.scala-lang.org/browse/SI-750