2010-06-11 36 views
9

ho il seguente codice in Java:Chiamata metodo Java vararg da Scala con primitive

public class JavaClass { 

    public static void method(Object x) { 
    } 

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

} 

Quando provo e accedervi da Scala,

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

ottengo il seguente errore di compilazione:

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]

Il messaggio di errore è molto utile e mostra come correggere l'errore, ma mi chiedevo perché il compilatore è (un pparently) felice di convertire implicitamente uno scala.Boolean in una chiamata di metodo ma non l'altra. È un bug o intenzionale?

Aggiornamento aggiornato per aggiungere: Sto usando Scala 2.8. Se eseguo la firma varargsMethod

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

, l'errore scompare. Sono ancora perplesso sul perché il compilatore non riesca a capirlo.

+0

GRAZIE! Questo trucco void varargsMethod (T ... xs) funziona !!! – ZiglioUK

risposta

5

Scala vararg e varargs Java sono diversi. È necessario do a conversion:

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

o (in 2.8.0+)

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

La versione 2.8 "Arrays.asList (true)" non funziona, in quanto fornisce un singolo argomento a "varargsMethod" di tipo "Array $ ArrayList". Tuttavia, trovare una soluzione alternativa non è davvero un problema - il messaggio di errore mostra come correggere l'errore - piuttosto volevo sapere perché il compilatore non compilerebbe questa chiamata quando lo farà per gli altri in situazioni simili. –

+0

Mi piacerebbe avere una risposta anche a questo. – Kevin

+0

quindi Scala> 2.8 restituisce il tipo BoxedObjectArray non è un membro del runtime del pacchetto – ZiglioUK

0

Probabilmente si può aprire un bug su di esso. Sembra che dovrebbe generare un'eccezione in entrambi i casi o nessuno dei due. Non sono sicuro che sia qualcosa che sarà mai risolto poichè probabilmente è causato da una certa abilità nell'implementazione di varargs che impedisce che la boxe abbia luogo.

2

Da scala.Boolean è una sottoclasse di scala.AnyVal ma non scala.AnyRef (tradotto java.lang.Object), un Boolean non possono essere passati ad un metodo attesa Object (s).

È possibile utilizzare l'oggetto compagna scala.Boolean a "scatola" (nel senso di Java, naturalmente) un boolean in java.lang.Boolean:

JavaClass.varargsMethod(Boolean.box(true)) 

Le altre classi sono AnyVal corrispondente box metodi (ad esempio Int.box). Ci sono anche i metodi unbox per fare il contrario.

Un più complicato caso d'uso:

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

non so quando questi sono stati aggiunti alla libreria standard, ma con questi non si dispone di utilizzare le classi di implementazione di scala.runtime.*.