Any,AnyVal,AnyRef,Object之间的关系是什么?在Java代码中如何映射?
我通常最终会尝试每个组合,直到它编译。 有人可以解释我应该在哪里使用?
在一个方面,我会不同意克里斯的 回答 。 Any
, AnyRef
和AnyVal
类都是类。 但是由于JVM的内在限制,它们不会以字节码forms出现。
这是因为并不是所有的Java都是一个对象。 除了对象之外,还有基元。 Java中的所有对象都是java.lang.Object
后代,但是原语被分开设置,目前*不能被程序员扩展。 还要注意,原语有“操作符”,而不是方法。
另一方面,在斯卡拉,一切都是一个对象,所有对象都属于一个类,它们通过方法进行交互。 生成的JVM字节码并不能反映这一点,但是这并没有使它们变得更小,就像Java具有generics一样,尽pipe字节码没有它们。
所以,在Scala中,所有的对象都是Any
后裔,包括Java认为的对象和Java认为的基元。 在Java中没有相同的东西,因为没有这种统一。
所有在Java中被认为是原始的东西都是Scala中的AnyVal
后裔。 在Scala 2.10.0之前, AnyVal
被封了,程序员无法扩展它。 看看.Net上的Scala会发生什么,应该很有趣,因为互操作性本身就要求Scala至less能够识别用户定义的“原语”。
还扩展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)
从class级层次上来看,每种方法都应该是明显的。 值得注意的是, f
和h
会自动装箱,但g
不会。 这与Java所做的有点相反,因为f
和h
不能被指定, g
(用java.lang.Object
定义)会导致自动装箱。
从Scala 2.10.0开始,用户可以使用以下语义扩展AnyVal
或Any
:
-
如果一个类扩展了
AnyVal
,那么在某些情况下堆中将不会创build任何实例。 这意味着这个类的字段(在2.10.0上只允许一个字段 – 不pipe这个字段是否将被改变)仍然保留在堆栈上,无论它们是原语还是对其他对象的引用。 这允许扩展方法没有实例化成本。 -
如果一个特征扩展了
Any
,那么它可以用于扩展AnyRef
类和扩展AnyRef
类。
PS:在我看来,Java很可能遵循C#来允许“struct”原语,也许typedef作为并行而不诉诸于它们,这很难以很好的性能完成。
看过这个? 该页面的文本有一些Java互操作性的评论。 http://www.scala-lang.org/node/128
Any
和AnyVal
是我认为是scala types系统的一部分, 不是类 (就像Nothing
types,也不是类)。 您不能在Java代码中显式使用它们。
不pipe怎样,在Java / Scala互操作中,接受Java Object
的方法将会得到一个Scala Any
/ AnyRef
。
你究竟想要做什么?