JUnit测试中的Kotlin内联类

JUnit测试中的Kotlin内联类,kotlin,junit,kotlin-experimental,kotlin-inline-class,Kotlin,Junit,Kotlin Experimental,Kotlin Inline Class,我试图理解内联类的概念——它们是运行时内联的单个属性的简单对象包装器。 这意味着,类的实际初始化不会在运行时发生 我试图编写一个简单的测试,它将在JUnit测试期间直接显示我的上述解释,如下所示: companion object { private const val NAME = "JACK" } inline class NameInlineClass(val value: String) @Test fun unwrapping() { val nameInlineCl

我试图理解内联类的概念——它们是运行时内联的单个属性的简单对象包装器。 这意味着,类的实际初始化不会在运行时发生

我试图编写一个简单的测试,它将在JUnit测试期间直接显示我的上述解释,如下所示:

companion object {
   private const val NAME = "JACK"
}

inline class NameInlineClass(val value: String)

@Test
fun unwrapping() {
    val nameInlineClass = NameInlineClass(NAME)
    val name = nameInlineClass
    assertEquals(name, NAME)
}

不幸的是,这个测试失败了,这就引出了一个问题:为什么在
assertEquals()
期间没有比较实际的未包装字符串值,而是比较实际的内联类(应该在运行时打开)?

您可能想做的是
val name=nameInlineClass.value
,但我会尽力解释错误

从文档中查看(包括代码示例):

在生成的代码中,Kotlin编译器为每个内联代码保留一个包装器 班级。内联类实例可以在运行时表示为 包装器或作为基础类型。这与Int的用法类似 表示为基本整数或包装整数

这意味着,只要不显式引用包装对象或其类型,值就不会被装箱。我们可以通过检查字节码(为了可读性而反编译回Java)来检查它:

我不会粘贴整个生成的
NameInlineClass
主体,但是
constructor impl
是一个静态方法,它只检查
value
null
,并且
box impl
创建包装器对象

您可以看到
nameInlineClass
实际上是一个
字符串
——这意味着内联工作,并且没有分配额外的对象

仅当引用
nameInlineClass
而不是
nameInlineClass.value
时,编译器确定此对象需要表示,并使用包装器
nameInlineClass
类“装箱”值

// kotlin source
fun unwrapping() {
    val nameInlineClass = NameInlineClass(NAME)
    val name = nameInlineClass  // this line gets dropped by compiler by the way
    assertEquals(name, NAME)
}

// java representation of bytecode
public final void unwrapping() {
   String nameInlineClass = NameInlineClass.constructor-impl("JACK");
   Assert.assertEquals(NameInlineClass.box-impl(nameInlineClass), "JACK");
}