Scala:将Any传递给一个接受java.lang.Object的方法

时间:2016-12-23 11:22:48

标签: scala

我对Scala的Anyjava.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类型的变量,为什么会这样?

2 个答案:

答案 0 :(得分:3)

编译器试图“弥补”Scala和Java类型系统之间的差异。在Scala中,Object =:= AnyRef(它们是别名)和AnyRef <: Any。因此,使用ObjectAnyRef的Scala方法无法使用AnyAnyVal。如果你想要一个适用于所有事情的方法,那么你会写Any,对吧?

然而,采用Object Java 方法通常意味着处理所有值,无论它们是实际的Object还是原语( intlong等),它们的工作原因是将原语装箱转换为Object s。基元和Object没有像Scala那样的常见超类型。 Java类型系统的表达力不足以区分“我只想要实际的对象”,“我将采取任何东西,无论是对象还是原始对象。”

因此,Scala编译器通过将Object的Java方法转换为Any的方法来对此进行补丁。此功能只是为了简化语言之间的互操作。但是,它不会将此转换应用于Scala代码,因为如果您想要这种行为,那么您实际上应该编写Any而不是Object

答案 1 :(得分:2)

原因是Any可以是AnyRefAnyVal,而method只能接受AnyRef的对象。如果您将a类型修改为AnyRef,它将起作用:

def method(input: java.lang.Object) = {}
val a: AnyRef = new Object
method(a)

如果调用静态Java方法,Scala编译器会将Any转换为Object,其中还包括AnyVal值的装箱。