内联类使用关键字 value 和 @JvmInline 注解声明,它只能有一个属性而且不能有 init 代码块和幕后字段
内联类有点像 Java 中的包装类型,Integer, Boolean 等等,而在使用内联类时,除非绝 对必要,否则类本身的信息不会在字节码中使用,而是将属性数据内联到类的使用处,可以 大大减少运行时的空间开销
@JvmInline // For JVM backends
value class Password(private val s: String)
在生成的代码中,Kotlin 编译器为每个内联类保留一个包装器。内联类的实例可以在运行 时表示为包装器或者基础类型,为了生成性能最优的代码,编译器更倾向于使用基础类型。 比如:
// 不存在 'Password' 类的真实对象
// 在运行时,'securePassword' 仅仅包含 'String'
val securePassword = Password("Don't try this in production")
但如果将内联类用作其他类型时,其类型信息是必须的,所以会被装箱。比如:
interface I
@JvmInline
value class Foo(val i: Int) : I
fun asInline(f: Foo) {}
fun <T> asGeneric(x: T) {}
fun asInterface(i: I) {}
fun asNullable(i: Foo?) {}
fun <T> id(x: T): T = x
fun main() {
val f = Foo(42)
asInline(f) // 拆箱操作: 用作 Foo 本身
asGeneric(f) // 装箱操作: 用作泛型类型 T
asInterface(f) // 装箱操作: 用作类型 I
asNullable(f) // 装箱操作: 用作不同于 Foo 的可空类型 Foo?
val c = id(f)
}