Home > OS >  Kotlin @JvmInline class broke class method names
Kotlin @JvmInline class broke class method names

Time:05-28

Faced with issue when using Kotlin value class annotated by @JvmInline

Here is an example:

@JvmInline
value class TestClass(val id: String)

interface TestInterface {

  fun doSomething(aVal: TestClass)

  fun callSomething(aVal: String)
}

fun main() {
  val clazz = TestInterface::class.java
  clazz.methods.forEach { println(it) }
}

Result output:

public abstract void TestInterface.callSomething(java.lang.String)
public abstract void TestInterface.doSomething-Qkb7kKY(java.lang.String)

Expected output:

public abstract void TestInterface.callSomething(java.lang.String)
public abstract void TestInterface.doSomething(java.lang.String)

Any ideas how to solve this issue without switching to data class?

CodePudding user response:

Value classes do not exist at runtime.

As you've seen from your output, the signature of your method is TestInterface.doSomething-Qkb7kKY(java.lang.String). Since value classes are essentially a runtime wrapper for their value, the true signature of the method has one String parameter. On compile time, it would be perfectly okay to add another overload to this method with a single String parameter, on runtime, this would cause a clash. Let's expand on your example;

@JvmInline
value class TestClass(val id: String)

interface TestInterface {
    fun doSomething(aVal: TestClass)
    fun doSomething(aVal: String)
    fun callSomething(aVal: String)
}

fun main() {
    val clazz = TestInterface::class.java
    clazz.methods.forEach { println(it) }
}

The output for the above would be the following and would therefore clash if it had the same name;

public abstract void TestInterface.callSomething(java.lang.String)
public abstract void TestInterface.doSomething(java.lang.String)
public abstract void TestInterface.doSomething-Qkb7kKY(java.lang.String)
  • Related