我对Scala的Any
与java.lang.Object
的关系感到困惑。我知道在scala中,AnyRef
对应object
,但是在java类或scala类中定义方法(取java.lang.Object
)似乎有所不同:
java class:
public class JavaClass {
public static void method(Object input) {
}
}
scala应用程序:
object ScalaObject extends App{
def method(input:java.lang.Object) = {}
val a:Any = null
method(a) // does not work
JavaClass.method(a) // does work
}
所以如果方法在java-Class中,那么编译器允许我传递Any
类型的变量,为什么会这样?
答案 0 :(得分:3)
编译器试图“弥补”Scala和Java类型系统之间的差异。在Scala中,Object =:= AnyRef
(它们是别名)和AnyRef <: Any
。因此,使用Object
或AnyRef
的Scala方法无法使用Any
或AnyVal
。如果你想要一个适用于所有事情的方法,那么你会写Any
,对吧?
然而,采用Object
的 Java 方法通常意味着处理所有值,无论它们是实际的Object
还是原语( int
,long
等),它们的工作原因是将原语装箱转换为Object
s。基元和Object
没有像Scala那样的常见超类型。 Java类型系统的表达力不足以区分“我只想要实际的对象”,“我将采取任何东西,无论是对象还是原始对象。”
因此,Scala编译器通过将Object
的Java方法转换为Any
的方法来对此进行补丁。此功能只是为了简化语言之间的互操作。但是,它不会将此转换应用于Scala代码,因为如果您想要这种行为,那么您实际上应该编写Any
而不是Object
。
答案 1 :(得分:2)
原因是Any
可以是AnyRef
或AnyVal
,而method
只能接受AnyRef
的对象。如果您将a
类型修改为AnyRef
,它将起作用:
def method(input: java.lang.Object) = {}
val a: AnyRef = new Object
method(a)
如果调用静态Java方法,Scala编译器会将Any
转换为Object
,其中还包括AnyVal
值的装箱。