Reputation: 3460
Supposed I have a Java API like below:
public class JavaApi<T> {
public void foo(T[] data) {
...
}
}
And I'd like to call it from Scala with the following class:
class Caller[T] {
val javaApi = new JavaApi[T]()
def callApi(data: Array[T]) = javaApi.foo(data)
}
On compile, I get the following:
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)
Upvotes: 1
Views: 4022
Reputation: 14217
This is caused by Java does not support polymorphic of primitive type.
Although Scala deal anything as Object but after compiler compile, maybe it will convert object to primitive type arrays for performance, such as:
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();
...
As you can see, the above Array[Int]
has been convert to int[]
primitive type arrays.
so for this reason, this maybe cause incompatible for Java method.
Solution:
T
to T <: AnyRef
. as val a = Array[Integer](1, 2, 3)
, the compiler will deal it as Integer[]
type.List
to replace Array
,List
always reference
type.Reference:
https://issues.scala-lang.org/browse/SI-750
Upvotes: 0
Reputation: 11655
You may review the Scala type hierarchy. More specifically the phrase:
If Scala is used in the context of a Java runtime environment, then scala.AnyRef corresponds to java.lang.Object
So, by changing it as Jubobs suggested you are sure that the type correspond to an object:
class Caller[T<: AnyRef] {
val javaApi = new JavaApi[T]()
def callApi(data: Array[T]) = javaApi.foo(data)
}
So if you need any value type like int, char, boolean you will need to convert them to their object equivalent boxed Java type like Integer, Character or Boolean. See:
Upvotes: 1