2010-06-11 22 views
9

tengo el siguiente código en Java:Llamando al método Java vararg de Scala con primitivas

public class JavaClass { 

    public static void method(Object x) { 
    } 

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

} 

Cuando intento acceder a ella desde Scala,

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

me sale el siguiente error de compilación:

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]

El mensaje de error es muy útil y muestra cómo solucionar el error, pero me preguntaba por qué es el compilador (pparently) feliz de convertir implícitamente un scala.Boolean en una llamada de método pero no en la otra. ¿Es esto un error o intencional?

Actualizado para añadir: Estoy usando Scala 2.8. Si hago la firma varargsMethod

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

en su lugar, el error también desaparece. Todavía estoy desconcertado sobre por qué el compilador no puede resolverlo.

+0

¡GRACIAS! Este truco void varargsMethod (T ... xs) funciona !!! – ZiglioUK

Respuesta

5

Scala varargs y Java varargs son diferentes. Es necesario que 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 versión de 2.8 "Arrays.asList (true)" no funciona, ya que da un solo argumento a "varargsMethod" del tipo "Arrays $ ArrayList". Sin embargo, encontrar una solución alternativa no es realmente un problema, el mensaje de error muestra cómo solucionar el error, sino que quería saber por qué el compilador no compilaría esta llamada cuando lo haría para otros en situaciones similares. –

+0

Me encantaría obtener una respuesta a esto también. – Kevin

+0

también lo hace Scala> 2.8 return type BoxedObjectArray no es miembro del tiempo de ejecución del paquete – ZiglioUK

0

probablemente puede reportar un fallo al respecto. Parece que debería arrojar una excepción en ambos casos o ninguno. No estoy seguro de que sea algo que alguna vez se solucione, ya que probablemente se debe a cierta astucia en la implementación de varargs que impide que se lleve a cabo el boxeo.

2

Desde scala.Boolean es una subclase de scala.AnyVal pero no scala.AnyRef (traducido a java.lang.Object), un Boolean no se puede pasar a un método esperando Object (s).

Usted puede utilizar el objeto compañero scala.Boolean a "caja" (en el sentido de Java, por supuesto) un boolean en java.lang.Boolean:

JavaClass.varargsMethod(Boolean.box(true)) 

Las otras clases han AnyVal correspondiente box métodos (por ejemplo Int.box). También hay unbox métodos para hacer lo contrario.

Un caso de uso más complicado:

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

No sé cuando estos se añaden a la biblioteca estándar, pero con ellos no tiene que utilizar las clases de implementación de scala.runtime.*.

Cuestiones relacionadas