I have kotlin value class:
@JvmInline
value class MyValueClass internal constructor(val rawValue: String) {
companion object {
@JvmName("myTestValueClass")
fun String.testValueClass(): MyValueClass {
return MyValueClass(
rawValue = "test",
)
}
}
}
And now I'm trying to use my value class from java code.
MyValueClass test = MyValueClass.Companion.myTestValueClass("test");
But I get error: Required MyValueClass provided String.
Why is this happening? Please, help me.
testValueClass
returns aString
because that is exactly the point of value classes - they are inlined.The whole point of value classes is that they are light-weight wrappers that has very little overhead. Kotlin tries very hard to not create instances of value classes.
In the JVM bytecode, value classes are replaced with the types they wrap, whenever possible, so that's why
testValueClass
returns aString
as far as Java is concerned. The generated bytecode fortestValueClass
would be equivalent toreturn "test";
.In Kotlin, you can still use members declared in
MyValueClass
even without creating an instance ofMyValueClass
:Recommended reading: Inline value classes in the Kotlin documentation.
In Java, however, there is no such language feature. If you want to call the
foo
method, you have to introduce an interface in Kotlin through whichfoo
can be called, and provide a method that returns that interface. By using an interface type as the return type, you force an instance of the value class to be created.Of course, you can also write a separate version of
myTestValueClass
that directly returns the interface.