Вызов метода Java vararg из Scala с примитивами - PullRequest
9 голосов
/ 11 июня 2010

У меня есть следующий код в Java:

public class JavaClass {

    public static void method( Object x ) {
    }

    public static void varargsMethod( Object... x ) {
    }

}

Когда я пытаюсь получить к нему доступ из Scala,

object FooUser {
  JavaClass.method(true)
  JavaClass.varargsMethod(true) // <-- compile error
}

Я получаю следующую ошибку компиляции:

несоответствие типов; Найдено: Boolean (true) Обязательно: java.lang.Object Примечание. Примитивные типы неявно не преобразуются в AnyRef. Вы можете безопасно форсировать бокс, применив x.asInstanceOf [AnyRef]

Сообщение об ошибке очень полезно и показывает, как исправить ошибку, но мне было интересно, почему компилятор (по-видимому) рад неявно преобразовать scala.Boolean в одном вызове метода, а не в другом. Это ошибка или умышленное?

Обновлено для добавления: Я использую Scala 2.8. Если я сделаю подпись varargsMethod

public static <T> void varargsMethod(T... xs) {

вместо этого ошибка также исчезнет. Я все еще озадачен, почему компилятор не может понять это.

Ответы [ 3 ]

5 голосов
/ 11 июня 2010

Scala varargs и Java varargs различны.Вам необходимо сделать преобразование :

def g(x: Any*) = x.asInstanceOf[scala.runtime.BoxedObjectArray]
.unbox(x.getClass)
.asInstanceOf[Array[Object]]  
...
JavaClass.varargsMethod(g(true))

или ( в 2.8.0 + )

JavaClass.varargsMethod(java.util.Arrays.asList(true))
2 голосов
/ 18 мая 2017

Поскольку scala.Boolean является подклассом scala.AnyVal, но не scala.AnyRef (в переводе java.lang.Object), Boolean нельзя передать методу, ожидающему Object (s).

Вы можете использовать сопутствующий объект scala.Boolean для "упаковки" (в смысле Java, конечно) boolean в java.lang.Boolean:

JavaClass.varargsMethod(Boolean.box(true))

Другие классы AnyVal имеют соответствующие box методы (например, Int.box). Существуют также unbox методы для обратного.

Более сложный вариант использования:

JavaClass.varargsMethod(Seq(1, 2, 3, 4).map(Int.box): _*) // passes 1, 2, 3, 4

Я не знаю, когда они были добавлены в стандартную библиотеку, но с ними вам не нужно использовать классы реализации scala.runtime.*.

0 голосов
/ 25 июля 2011

Вероятно, может подать ошибку об этом.Похоже, он должен выдать исключение в обоих случаях или ни того, ни другого.Не уверен, что это что-то, что когда-либо будет исправлено, так как это, вероятно, вызвано некоторой хитростью в реализации varargs, которая предотвращает бокс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...