2017-02-02 5 views
1

Предполагается У меня есть Java API, как показано ниже:Scala вызова метода Java с параметром массива

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) 
+3

Потому что ваш Scala код место нет типа ограничений на 'Т *, последнее может быть' AnyVal', что несовместимо с кодом Java. Поэтому вы должны определить свой класс 'Caller' как' class Caller [T <: AnyRef] {...} '. – Jubobs

+0

Спасибо, что очищает вопрос компиляции.Но я думал, что при компиляции все классы внедряются в Object независимо от того, является ли это scala или java-классом? – Wins

+0

Я не понимаю, что вы подразумеваете под этим ... – Jubobs

ответ

0

Вы можете рассмотреть Scala type hierarchy. Более конкретно фраза:

Если Scala используется в контексте среды выполнения Java, а затем scala.AnyRef соответствует интерфесам

Таким образом, путем изменения его как предложено Jubobs вы уверены, что тип соответствуют объекту:

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

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

Так что если вам нужен любой тип значения, как межд, полукокса, булевы вам нужно будет преобразовать их в объект эквивалент коробочного типа Java, как Integer, Character или Бо Олин. См: enter image description here

0

Это вызвано Java не поддерживает полиморфный из primitive type.

Хотя Scala сделки ничего как Object, но после того, как компилятор компиляции, может быть, это будет конвертировать объект в массивы примитивных типов для исполнения, такие как:

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 для замены Array, List всегда reference тип.

Ссылка:

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

Смежные вопросы