2010-06-11 17 views
9

Mam następujący kod w Javie:Wywołanie metody Java vararg od Scala z prymitywów

public class JavaClass { 

    public static void method(Object x) { 
    } 

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

} 

Gdy próbuję i do niego dostęp z Scala,

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

otrzymuję następujący błąd kompilacji:

type mismatch; found : Boolean(true) required: java.lang.Object Note: primitive types are not implicitly converted to AnyRef. You can safely force boxing by casting x.asInstanceOf[AnyRef]

Komunikat o błędzie jest bardzo pomocny i pokazuje, jak naprawić błąd, ale zastanawiałem się, dlaczego kompilator jest (pparently) z przyjemnością niejawnie konwertować scala.Boolean w jednym wywołaniu metody, ale nie w drugim. Czy to błąd, czy zamierzony?

Zaktualizowano, aby dodać: Używam Scala 2.8. Jeśli zamiast tego podpiszę podmienną metrum, będzie to oznaczać, że błąd również zniknie. Nadal jestem zdziwiony, dlaczego kompilator nie może tego rozgryźć.

+0

DZIĘKUJEMY! Ta sztuczka void varargsMethod (T ... xs) działa !!! – ZiglioUK

Odpowiedz

5

Scala varargs i Java varargs są różne. Trzeba do a conversion:

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

lub (in 2.8.0+)

JavaClass.varargsMethod(java.util.Arrays.asList(true)) 
+3

Wersja 2.8 "Arrays.asList (true)" nie działa, ponieważ podaje pojedynczy argument "varargsMethod" typu "Array $ ArrayList". Jednak znalezienie obejścia problemu nie stanowi problemu - komunikat o błędzie pokazuje, jak naprawić błąd - raczej chciałem się dowiedzieć, dlaczego kompilator nie skompilowałby tego połączenia, kiedy będzie on dla innych w podobnych sytuacjach. –

+0

Chciałbym również uzyskać odpowiedź na to pytanie. – Kevin

+0

, podobnie jak Scala> 2.8 typ zwrotu BoxedObjectArray nie jest członkiem środowiska wykonawczego pakietów – ZiglioUK

0

Prawdopodobnie może zgłosić błąd o tym. Wygląda na to, że powinien wyrzucić wyjątek w obu przypadkach. Nie jestem pewien, czy to coś, co kiedykolwiek zostanie naprawione, ponieważ prawdopodobnie jest spowodowane pewną sprytnością w implementacji varargs, która uniemożliwia boksowanie.

2

Ponieważ scala.Boolean to podklasa scala.AnyVal ale scala.AnyRef (w przeliczeniu na java.lang.Object), A Boolean nie mogą być przekazywane do sposobu oczekiwano Object (S).

Można użyć obiektu towarzysz scala.Boolean do "box" (w sensie Javy, oczywiście) A boolean do java.lang.Boolean:

JavaClass.varargsMethod(Boolean.box(true)) 

Pozostałe AnyVal zajęcia mają odpowiednie box metod (np Int.box). Istnieją również metody, aby zrobić odwrotnie.

Bardziej skomplikowany przypadek użycia:

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

Nie wiem, kiedy te zostały dodane do biblioteki standardowej, ale z nich nie trzeba używać klas wdrażania scala.runtime.*.

Powiązane problemy