我通常会尝试每一种组合,直到编译完成。有人能解释一下我应该在哪里使用哪种组合吗?
我相信,Any和 AnyVal是 scala 打字系统和 不是这样的类的一部分(就像 Nothing是一种类型,而不是一个类一样)。您不能在 Java 代码中显式地使用它们。
Any
AnyVal
Nothing
Howwever, in Java/Scala interoperation, a method which accepts a Java Object will expect a scala Any / AnyRef.
Object
AnyRef
你到底想做什么?
看到这个了吗? 这个页面的文本有一些 Java 互操作性的注释。 Http://www.scala-lang.org/node/128
我不同意 克里斯的 回答在一个方面。类 Any、 AnyRef和 AnyVal are类。但是由于 JVM 的内在限制,它们不会以字节码中的类的形式出现。
这是因为 Java 中并非所有东西都是对象。除了对象之外,还有原语。Java 中的所有对象都是 java.lang.Object的后代,但是原语是分开的,目前 *不能由程序员扩展。还要注意,原语具有“运算符”,而不是方法。
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 之前,用户不能扩展 Any或 AnyVal,也不能从 Java 引用它们,但是在 Scala 中可以使用 曾经是的其他用途。具体来说,类型签名:
def f(x: AnyVal) = println(x) def g(x: AnyRef) = println(x) def h(x: Any) = println(x)
从类层次结构来看,每个意思都应该是显而易见的。然而,值得注意的是,f和 h将自动框,但 g不会。这与 Java 的做法有点相反,因为不能指定 f和 h,而且 g(用 java.lang.Object定义)会导致自动装箱。
f
h
g
但是,从 Scala 2.10.0开始,用户可以使用以下语义扩展 AnyVal或 Any:
如果一个类扩展了 AnyVal,在特定条件下将不会在堆上为它创建任何实例。这意味着这个类的字段(在2.10.0上只允许一个字段——是否会发生变化还有待观察)将保留在堆栈上,无论它们是原语还是对其他对象的引用。这使得扩展方法不需要实例化成本。
如果 trait 扩展了 Any,那么它可以用于扩展 AnyRef的类和扩展 AnyVal的类。
PS: 在我看来,Java 很可能会效仿 C # ,允许“ struct”原语,或者 typedef,因为不使用它们的并行性很难以良好的性能实现。