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

时间:2010-02-25 15:49:03

标签: scala

我通常最终尝试每个组合,直到它编译。有人可以解释我应该在哪里使用吗?

3 个答案:

答案 0 :(得分:119)

我在一方面不同意Chris's answer。类AnyAnyRefAnyVal 类。但由于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至少能够识别用户定义的“原语”。

同样扩展AnyAnyRef,相当于java.lang.Object(无论如何都在JVM上)。

直到Scala 2.9.x,用户无法扩展AnyAnyVal,也无法从Java引用它们,但 其他用途可以放到在斯卡拉。具体来说,键入签名:

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定义)会导致自动装箱。< / p>

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

  • 如果类扩展AnyVal,则在某些条件下不会在堆上为它创建任何实例。这意味着这个类的字段(在2.10.0上只允许一个字段 - 无论是否会改变还有待观察)将保留在堆栈中,无论它们是基元还是对其他对象的引用。这允许扩展方法没有实例化成本。

  • 如果特征扩展Any,那么它可以与扩展AnyRef的类和扩展AnyVal的类一起使用。

PS:在我看来,Java可能会遵循C#来允许“struct”原语,也许是typedef,因为没有求助于它们的并行性很难以良好的性能来实现。

答案 1 :(得分:39)

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

Scala Class Heierarchy

答案 2 :(得分:4)

我认为,

AnyAnyVal是scala 类型系统的一部分而不是类(以同样的方式) Nothing是一个类型,而不是一个类。您无法在Java代码中明确使用它们。

但是,在Java / Scala互操作中,接受Java Object的方法将需要scala Any / AnyRef

你究竟想做什么?