What are the relationships between Any, AnyVal, AnyRef, Object and how do they map when used in Java code?

我通常会尝试每一种组合,直到编译完成。有人能解释一下我应该在哪里使用哪种组合吗?

29111 次浏览

我相信,AnyAnyVal是 scala 打字系统不是这样的类的一部分(就像 Nothing是一种类型,而不是一个类一样)。您不能在 Java 代码中显式地使用它们。

Howwever, in Java/Scala interoperation, a method which accepts a Java Object will expect a scala Any / AnyRef.

你到底想做什么?

看到这个了吗? 这个页面的文本有一些 Java 互操作性的注释。 Http://www.scala-lang.org/node/128

Scala Class Heierarchy

我不同意 克里斯的 回答在一个方面。类 AnyAnyRefAnyVal are类。但是由于 JVM 的内在限制,它们不会以字节码中的类的形式出现。

这是因为 Java 中并非所有东西都是对象。除了对象之外,还有原语。Java 中的所有对象都是 java.lang.Object的后代,但是原语是分开的,目前 *不能由程序员扩展。还要注意,原语具有“运算符”,而不是方法。

另一方面,在 Scala 中,所有的 都是一个对象,所有的对象都属于一个类,它们通过方法进行交互。生成的 JVM 字节码并没有反映这一点,但这并不意味着它们就不那么重要了,就像 Java 有泛型一样,即使字节码没有泛型。

因此,在 Scala 中,所有对象都是 Any的后代,包括 Java 认为的对象和 Java 认为的原语。在 Java 中没有等价物,因为没有这样的统一。

Java 中所有被认为是原语的东西都是 Scala 中 AnyVal的后代。在 Scala 2.10.0之前,AnyVal是密封的,程序员无法扩展它。看看 Scala 运行后会发生什么应该很有趣。Net,因为仅互操作性就要求 Scala 至少能够识别用户定义的“原语”。

同样扩展 Any的还有 AnyRef,它等价于 java.lang.Object(无论如何在 JVM 上)。

在 Scala 2.9. x 之前,用户不能扩展 AnyAnyVal,也不能从 Java 引用它们,但是在 Scala 中可以使用 曾经是的其他用途。具体来说,类型签名:

def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)

从类层次结构来看,每个意思都应该是显而易见的。然而,值得注意的是,fh将自动框,但 g不会。这与 Java 的做法有点相反,因为不能指定 fh,而且 g(用 java.lang.Object定义)会导致自动装箱。

但是,从 Scala 2.10.0开始,用户可以使用以下语义扩展 AnyValAny:

  • 如果一个类扩展了 AnyVal,在特定条件下将不会在堆上为它创建任何实例。这意味着这个类的字段(在2.10.0上只允许一个字段——是否会发生变化还有待观察)将保留在堆栈上,无论它们是原语还是对其他对象的引用。这使得扩展方法不需要实例化成本。

  • 如果 trait 扩展了 Any,那么它可以用于扩展 AnyRef的类和扩展 AnyVal的类。

PS: 在我看来,Java 很可能会效仿 C # ,允许“ struct”原语,或者 typedef,因为不使用它们的并行性很难以良好的性能实现。