Any,AnyVal,AnyRef,Object之间有什么关系?在Java代码中使用它们时如何映射?


110

我通常最终会尝试所有组合,直到其编译为止。有人可以解释我应该在哪里使用吗?

Answers:


124

我会在一个方面不同意克里斯的 回答。该班AnyAnyRefAnyVal 类。但是由于JVM的固有限制,它们不会在字节码中显示为类。

这是由于Java中的并非所有对象都是对象而产生的。除了对象之外,还有其他原语。Java中的所有对象都是的后代java.lang.Object,但原语是​​分开设置的,并且当前*是不能由程序员扩展的。还请注意,原语具有“运算符”,而不具有方法。

另一方面,在Scala中,一切都是对象,所有对象都属于一个类,并且它们通过方法进行交互。生成的JVM字节码不能反映出这一点,但这并不能使它们变得如此,就像Java具有泛型一样,即使字节码没有泛型也是如此。

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

Java中所有被认为是原始的东西都是AnyValScala的后代。在AnyVal密封Scala 2.10.0之前,程序员无法对其进行扩展。有趣的是,在.Net上看到Scala会发生什么,因为互操作性仅要求Scala至少识别用户定义的“基元”。

还延伸AnyAnyRef,这相当于java.lang.Object(在JVM上在任何速率)。

截至斯卡拉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那样,在对面f,并h不能指定,g(有定义java.lang.Object)会导致自动装箱。

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

  • 如果类扩展AnyVal,则在某些情况下不会在堆上为其创建实例。这意味着此类的字段(在2.10.0上仅允许单个字段-是否会更改仍待观察)将保留在堆栈中,无论它们是原语还是对其他对象的引用。这允许扩展方法而无需实例化成本。

  • 如果特征扩展Any,则可以将其与扩展AnyRef类和扩展类一起使用AnyVal

PS:在我看来,Java可能会遵循C#来允许“结构”原语,甚至可能是typedef,因为事实证明,不求助于它们的并行性很难以良好的性能实现。


2
更新:从Scala 2.9.2开始,AnyVal定义为sealed trait AnyVal extends Any。但是在Scala 2.10中,它已更改为abstract class AnyVal extends Any with NotNull,现在可以AnyVal使用新的值类功能进行扩展,例如:class MyValue(val u: Int) extends AnyVal
ebruchez 2012年

@ebruchez感谢您的来信。我已经用新功能的概述更新了答案。
Daniel C. Sobral

Nothing和Null与这有什么关系?
Gaurav Khare


5

AnyAnyVal是,我相信,阶的部分类型的系统不阶级作为(在相同的方式Nothing是一种类型的,而不是一个类)。您不能在Java代码中显式使用它们。

但是,在Java / Scala互操作中,接受Java的方法Object将期望使用scala Any/ AnyRef

您实际上在尝试做什么?


我试图更好地理解该主题,以便我知道在计划Java调用Scala时应该使用哪种类型,反之亦然。这个答案stackoverflow.com/questions/2334200/…及其强制转换AnyRef只是提醒我,这对我来说仍然很神秘。
huynhjl
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.