Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
377 views
in Technique[技术] by (71.8m points)

scala - What are the relationships between Any, AnyVal, AnyRef, Object and how do they map when used in Java code?

I usually end up trying every combination until it compiles. Can somebody explain what I should use where?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'll disagree with Chris's answer in one regard. The classes Any, AnyRef and AnyVal are classes. But they don't appear as classes in bytecode, because of intrinsic limitations of the JVM.

This arises out of the fact that not everything in Java is an object. In addition to objects, there are primitives. All objects in Java are descendant from java.lang.Object, but primitives are set apart and, presently*, not extensible by a programmer. Note also that primitives have "operators", not methods.

In Scala, on the other hand, everything is an object, all objects belong to a class, and they interact through methods. The JVM bytecode generated does not reflect this, but that doesn't make them any less so, just as Java has generics, even though the bytecode doesn't have them.

So, in Scala, all objects are descendant from Any, and that includes both what Java considers objects and what Java considers primitives. There's no equivalent in Java because there is no such unification.

Everything that is considered a primitive in Java is descendant from AnyVal in Scala. Until Scala 2.10.0, AnyVal was sealed, and programmers were unable to extend it. It should be interesting to see what will happen with Scala on .Net, since interoperability alone calls for Scala to at least recognize user-defined "primitives".

Also extending Any is AnyRef, which is equivalent to java.lang.Object (on the JVM at any rate).

Up to Scala 2.9.x, a user could not extend Any or AnyVal, nor reference them from Java, but there were other uses they could be put to in Scala. Specifically, type signatures:

def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)

What each means should be obvious from the class hierarchy. Of note, however, is that f and h will auto-box, but g will not. That is a bit the opposite of what Java does, in that f and h cannot be specified, and g (defined with java.lang.Object) would cause auto-boxing.

Starting with Scala 2.10.0, though, the user can extend AnyVal or Any, with the following semantics:

  • If a class extends AnyVal, no instance will be created for it on the heap under certain conditions. This means the fields of this class (on 2.10.0 only a single field is allowed -- whether that will change remains to be seen) will stay on the stack, whether they are primitives or references to other objects. This allows extension methods without the instantiation cost.

  • If a trait extends Any, then it can be used with both classes that extend AnyRef and classes that extend AnyVal.

PS: In my own view, Java is likely to follow C# in allowing "struct" primitives, and maybe typedefs, as parallelism without resorting to them is proving difficult to accomplish with good performance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...