In all three cases, there will be no boxing at all.
It is very easy to check yourself:
class ActionId(val value: Int) extends AnyVal object Foo { def someFunction(): ActionId = { new ActionId(123) } }
Now let's run scalac and we will have a bunch of class files (bytecode files). We need foo \ $.
» javap Foo\$ Compiled from "Boxing.scala" public final class Foo$ extends java.lang.Object{ public static final Foo$ MODULE$; public static {}; public int someFunction(); }
As you can see, even if the class of values leaks out of the function at all, it will not be placed in the box.
case class Post(id: ActionId, notion: String) object Foo2 { def someFunction(): Post = { Post(new ActionId(123), "So ActionID will be boxed?") } }
scalac => javap:
» javap Post Compiled from "Boxing.scala" public class Post extends java.lang.Object implements scala.Product,scala.Serializable{ public static scala.Function1 tupled(); public static scala.Function1 curried(); public int id(); public java.lang.String notion(); public Post copy(int, java.lang.String); public int copy$default$1(); public java.lang.String copy$default$2(); public java.lang.String productPrefix(); public int productArity(); public java.lang.Object productElement(int); public scala.collection.Iterator productIterator(); public boolean canEqual(java.lang.Object); public int hashCode(); public java.lang.String toString(); public boolean equals(java.lang.Object); public Post(int, java.lang.String); }
As you can see, id is presented here as a simple int (for example, the third method).
Finally, will the boxed class cost if the object with the member of the value class is not returned (really does not go out of scope)?
case class Post(id: ActionId, notion: String) object Foo3 { def anotherFunction(): Unit { val post = Post(new ActionId(123), "Will be boxed?") } }
If we carefully consider the byte code of the method, here is what we will see:
Code: Stack=4, Locals=2, Args_size=1 0: new
In ActionId there is no box for int. If it is in the box, you will see something like this:
Code: Stack=5, Locals=2, Args_size=1 0: new
You see, the difference is bipush 123 vs
4: new