# Autoboxing inline classes for Java interop?

**URL:** <https://discuss.kotlinlang.org/t/autoboxing-inline-classes-for-java-interop/22534>\
**Category:** Language Design\
**Created:** [July 26, 2021, 8:58pm UTC](https://discuss.kotlinlang.org/t/autoboxing-inline-classes-for-java-interop/22534 "2021-07-26T20:58:33Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![stachenov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/stachenov/32/6199_2.png) [@stachenov](https://discuss.kotlinlang.org/u/stachenov)\
**Post date:** [July 26, 2021, 8:58pm UTC](https://discuss.kotlinlang.org/t/autoboxing-inline-classes-for-java-interop/22534/1 "2021-07-26T20:58:33Z")

</div>

I’m migrating some code to Kotlin 1.5, and I’d really like to use inline classes for some very widely used library classes. However, these are used by _a lot_ of Java code, and while ABI compatibility is not an issue, source compatibility is. These classes usually follow a kind of “sealed private data class” pattern to avoid the public `copy()` issue:

```auto
sealed class MyValueClass {
    abstract val value: Int
    fun acceptInt(i: Int) { }
    fun acceptMyClass(other: MyValueClass) { }
    fun returnMyClass(): MyValueClass = this

    companion object {
        @JvmStatic fun of(value: Int): MyValueClass = MyValueClassImpl(value)
        @JvmField val ZERO: MyValueClass = MyValueClassImpl(0)
    }

    private data class MyValueClassImpl(override val value: Int): MyValueClass()
}

```

While this isn’t as elegant as it could be if I could simply use a data class without a `copy()` function, it works just perfectly. Now when I’m trying to make it an inline class, all kinds of things go wrong as far as Java interop is concerned.

```auto
@JvmInline
value class MyValueClass private constructor(val value: Int) {
    fun acceptInt(i: Int) { }
    fun acceptMyClass(other: MyValueClass) { }
    fun returnMyClass(): MyValueClass = this

    companion object {
        @JvmStatic fun of(value: Int): MyValueClass = MyValueClass(value)
        @JvmField val ZERO: MyValueClass = MyValueClass(0)
    }
}

```

What happens is:

- the `acceptInt` function is compiled into a static function accepting two `int`s (`this` and `i`);
- the same goes for `acceptMyClass`, as `other` is an `int` too;
- the `returnMyClass` function returns an `int`;
- the `of` function returns an `int` too;
- the `ZERO` constant doesn’t even compile because a `@JvmField` can’t be of an inline class type.

And with the name mangling I can’t even use most (all?) of these functions from Java even if I was willing to work with `int`s directly (thereby turning all this stuff into procedural type-unsafe programming).

What could be _really_ useful here is to somehow get it work transparently with Java, even if at the cost of autoboxing. But I see no magic annotation or compiler option for that. What I really want to have is an unmangled boxed counterpart for every function, so that `of` returns a `MyValueClass` instance when called from Java, and an `Int` when called from Kotlin.

I actually managed to get it done with some hardcore interface abuse:

```auto
sealed interface MyValueClass {
    val value: Int
    fun acceptInt(i: Int)
    fun acceptMyClass(other: MyValueClass)
    fun returnMyClass(): MyValueClass

    companion object {
        @JvmStatic fun of(value: Int): MyValueClass = MyValueClassImpl.of(value)
        @JvmField val ZERO: MyValueClass = MyValueClassImpl.ZERO
    }
}

@JvmInline
value class MyValueClassImpl(override val value: Int): MyValueClass {
    override fun acceptInt(i: Int) { }
    override fun acceptMyClass(other: MyValueClass) = acceptMyClass(other as MyValueClassImpl)
    fun acceptMyClass(other: MyValueClassImpl) { }
    override fun returnMyClass() = this

    companion object {
        fun of(value: Int) = MyValueClassImpl(value)
        val ZERO = MyValueClassImpl(0)
    }
}

```

This isn’t as ugly as using `int`s directly from Java would be, but it’s still far from perfect. Not only it’s too verbose (which is an acceptable price for an optimization), but the need to use `MyValueClassImpl` everywhere in Kotlin is very annoying (and makes converting Java code to Kotlin code harder). This is an acceptable price for an optimization as well, but is on the verge of being too complicated.

What’s especially frustrating is that Kotlin already generates a boxing class for a value class. All it needs to do is to add all members to it (with companion object members, I can live with special overloads for Java). But instead of implementing member functions as true members, it simply unboxes `this` on every call, and then passes the unboxed value to the static implementation, that is mangled and inaccessible from Java (and is useless anyway even if I unmangle it with `@JvmName`).
