In these cases, the Scala value class will be “boxed”, right?

后端 未结 3 663
-上瘾入骨i
-上瘾入骨i 2021-01-02 13:51

If I have this value class:

class ActionId(val value: Int) extends AnyVal

Then, in all the examples below, an object will be allocated for

3条回答
  •  南笙
    南笙 (楼主)
    2021-01-02 14:44

    None of your examples result in boxing. Value classes are only boxed with generics, with arrays, and when typed as a superclass/trait (e.g. Any/AnyVal)

    They're boxed with generics because otherwise you can't distinguish them from the value (and primitives need a box anyway). Same deal with Any, and other superclasses/traits need a box or the type relationship is wrong.

    They're boxed with arrays because arrays need to know the type of the contents, but the JVM doesn't understand the concept of a "value type". So you'd end up with an array that said it was the type being boxed, but which Scala was pretending was an array of the value type; a decision was made (based on previous issues with Array when it wasn't just a plain Java/JVM array) that this would lead to too many subtle bugs and corner cases.

    Here's an example of the three ways to get boxing:

    trait Q extends Any {}
    class X(val x: String) extends AnyVal with Q {}
    
    // Array
    val a = Array(new X("salmon"))   // boxed
    
    // Generic
    val b = Option(new X("minnow"))  // boxed
    
    // Upcast
    val c = (new X("perch"): Any)    // boxed
    val d = (new X("cod"): AnyVal)   // boxed
    val e = (new X("herring"): Q)    // boxed
    

    Everything else--passing around through various functions, etc.--doesn't require boxing, including all of your examples.

    Arrays are a bit of a special case because you can store the primitives and pull them out again as value classes with zero bytecode overhead, but a lot of syntactic overhead:

    class Y(val repr: String) extends AnyVal {}
    val y1 = new Y("apple")    // unboxed
    val y2 = new Y("orange")   // unboxed
    val ys: Array[String] = Array(y1.repr, y2.repr)   // no overhead
    val y3 = new Y(ys(0))      // no overhead
    

提交回复
热议问题