我通常最终尝试每个组合,直到它编译。有人可以解释我应该在哪里使用吗?
答案 0 :(得分:119)
我在一方面不同意Chris's answer。类Any
,AnyRef
和AnyVal
是类。但由于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,用户无法扩展Any
或AnyVal
,也无法从Java引用它们,但 其他用途可以放到在斯卡拉。具体来说,键入签名:
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
定义)会导致自动装箱。< / p>
从Scala 2.10.0开始,用户可以使用以下语义扩展AnyVal
或Any
:
如果类扩展AnyVal
,则在某些条件下不会在堆上为它创建任何实例。这意味着这个类的字段(在2.10.0上只允许一个字段 - 无论是否会改变还有待观察)将保留在堆栈中,无论它们是基元还是对其他对象的引用。这允许扩展方法没有实例化成本。
如果特征扩展Any
,那么它可以与扩展AnyRef
的类和扩展AnyVal
的类一起使用。
答案 1 :(得分:39)
看到这个?该页面的文本有一些Java互操作性备注。 http://www.scala-lang.org/node/128
答案 2 :(得分:4)
Any
和AnyVal
是scala 类型系统的一部分而不是类(以同样的方式) Nothing
是一个类型,而不是一个类。您无法在Java代码中明确使用它们。
但是,在Java / Scala互操作中,接受Java Object
的方法将需要scala Any
/ AnyRef
。
你究竟想做什么?