I'm not sure how boxing works sometimes with inlin...
# getting-started
j
I'm not sure how boxing works sometimes with inline classes, or rather why it works that way. Here's a simple example:
Copy code
@JvmInline
value class Wrapper(val value: CharSequence) : CharSequence by value
Here, since the inline class and its underlying value both implement the
CharSequence
interface, I could write either:
Copy code
val wrappedValue: CharSequence = Wrapper("foo")
// OR
val wrappedValue: CharSequence = "foo"
But, in the first case, the value seems to be boxed:
Copy code
@NotNull
   private static final CharSequence wrappedValue = Wrapper.box-impl(Wrapper.constructor-impl((CharSequence)"foo"));
There is probably a reason, but I don't get it. 🤔
I wanted to use inline classes to clarify some types returned by my library. Instead of having:
Copy code
fun someFun(): Set<List<String>>
I would like to provide something a bit more readable:
Copy code
fun someFun(): Set<ExplicitType>
Since I need the collections, should I go with a type alias instead of an inline class?
e
how do you imagine it would work if it weren't boxed?
j
In my first message, the inline class and the underlying value implement the same interface, so I imagine they are interchangeable? And about collections, or generics in a general manner, honestly I don't know, I'm out of my league there. 😅 But I'm not searching for an explanation, just for an answer to my question "it seems like using inline classes inside collections is a bad idea?"
e
they are not interchangeable,
wrappedValue is Wrapped
evaluates differently
it's not necessarily a bad idea, but it is in line with everything else. primitives are also boxed when used through a generic or reference type
j
Ah! You’re right, thank you 😅
So, since using inline classes seems to bring a lot of performance issues in my use case (generics). What is recommended? Using a standard class? A typealias? (are those even publicly available when a library uses them internally?)
j
Basically every time a value class is used as another type (generics, superclass, superinterface, etc.) it is boxed
thank you color 1
👍 1
e
you can't have a superclass of a value class (beyond
Any
which is special) but yes
s
so always use the WrappedType and most of the time at runtime it will just be the basic type without overhead 😂
j
Couldn't this be an issue? Since boxing/unboxing could happen multiple times for the same value. For example, the following code:
Copy code
fun main() {
    val list = listOf(Wrapper("foo"))
    val second = list.first()
    val third = listOf(second)
}
Generates:
Copy code
List list = CollectionsKt.listOf(Wrapper.box-impl(Wrapper.constructor-impl("foo")));
      String second = ((Wrapper)CollectionsKt.first(list)).unbox-impl();
      List third = CollectionsKt.listOf(Wrapper.box-impl(second));
You can see it boxes, unboxes, and boxes again.
but maybe this is premature optimization 🤔