Som Bhattacharyya Som Bhattacharyya - 6 months ago 10x
Java Question

What is the difference in memory allocation of objects extending AnyVal and AnyRef

So in Java we see that primitive types take up less memory space than their object counterparts. For example an

will take less space than an instance of
For which reason its often more sensible to
instead of
to store single characters.

I want to understand how does this translate to Scala.
There are no primitives. All we have are instances of
Is there are difference between the memory allocations for each ?


Is there are difference between the memory allocations for each

AnyRef is similar to inherting object, where you get the normal overhead of 8/16 bytes for x86/x64 respectively for every object because of headers.

AnyVal in Scala allows to optimize a very specific use case where you have a single val parameter which is wrapped in a class, and you can represent the said class as the underlying value at runtime, instead of allocating an instance of the class.

AnyVal has several restrictions:

  1. Must have only a primary constructor with exactly one public, val parameter whose type is not a value class. (From Scala 2.11.0, the parameter may be non-public.)
  2. May not have specialized type parameters.
  3. May not have nested or local classes, traits, or objects
  4. May not define a equals or hashCode method.
  5. Must be a top-level class or a member of a statically accessible object
  6. Can only have defs as members. In particular, it cannot have lazy vals, vars, or vals as members.
  7. Cannot be extended by another class.

For example, if we take the example from the documentation:

class Wrapper(val underlying: Int) extends AnyVal {
  def foo: Wrapper = new Wrapper(underlying * 19)

The representation of Wrapper at compile time is still a class. But at runtime, the underlying representation will be an Int, instead of a class Wrapper with an additional Int field.

But it isn't always guaranteed that Wrapper will become an Int representation at runtime. It won't when:

  1. A value class is treated as another type.
  2. A value class is assigned to an array.
  3. Doing runtime type tests, such as pattern matching.