我在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
}
我收到以下编译错误:
类型不匹配; found:Boolean(true)required:java.lang.Object注意:基本类型不会隐式转换为AnyRef。你可以通过施放x.asInstanceOf [AnyRef]
来安全地强制拳击
错误消息非常有用,并显示了如何修复错误,但我想知道为什么编译器(显然)很乐意在一个方法调用中隐式转换scala.Boolean
而不是另一个方法调用。这是一个错误还是故意的?
已更新以添加: 我正在使用Scala 2.8。如果我制作varargsMethod签名
public static <T> void varargsMethod(T... xs) {
相反,然后错误也消失了。我仍然感到困惑,为什么编译器无法解决这个问题。
答案 0 :(得分:5)
Scala varargs和Java varargs不同。您需要do a conversion:
def g(x: Any*) = x.asInstanceOf[scala.runtime.BoxedObjectArray]
.unbox(x.getClass)
.asInstanceOf[Array[Object]]
...
JavaClass.varargsMethod(g(true))
或(in 2.8.0+)
JavaClass.varargsMethod(java.util.Arrays.asList(true))
答案 1 :(得分:2)
由于scala.Boolean
是scala.AnyVal
但不是scala.AnyRef
(已翻译为java.lang.Object
)的子类,因此无法将Boolean
传递给期望Object
的方法1}}(一个或多个)。
您可以使用随附对象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.*
的实现类。
答案 2 :(得分:1)
请注意,在Scala 2.13.x版本中,这是开箱即用的功能(无需双关语),而无需手动将值装箱。
答案 3 :(得分:0)
可能会提交有关它的错误。似乎它应该在两种情况下都抛出异常,或者两者都不抛出异常。不确定它是否会被修复,因为它可能是由于varargs的实现中的一些聪明而导致阻止拳击发生。