0Pricing
Kotlin Academy · 课时

限制

了解值类无法完成的操作

限制 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。

了解边界

值类功能强大,但也受到限制。了解这些限制,可以帮助您选择合适的工具并避免意外情况。

恰好一个属性

值类包装单个值。要组合多个字段,您需要使用普通类或 data class。

// @JvmInline value class Range(val lo: Int, val hi: Int) // not allowed

data class Range(val lo: Int, val hi: Int)

fun main() {
    println(Range(1, 10))
}

值之外不允许有初始化状态

除了唯一的构造函数属性之外,值类不能拥有其他幕后字段。不允许使用带幕后字段的额外 var 状态。

@JvmInline
value class Counter(val value: Int) {
    // val cached: Int = value * 2  // not allowed: extra backing field
    val doubled: Int get() = value * 2  // computed is fine
}

fun main() {
    println(Counter(3).doubled)
}

不支持继承

值类会隐式声明为 final。它们不能扩展其他类,也不能被扩展。它们只能实现接口。

interface Named { val label: String }

@JvmInline
value class Tag(val text: String) : Named {
    override val label: String get() = text
}

fun main() {
    println(Tag("urgent").label)
}

装箱会带来开销

当值被用作可空类型、泛型类型或接口类型时,零开销的承诺就会消失。此时编译器会将它装箱为一个真正的对象。

@JvmInline
value class Id(val raw: Int)

fun main() {
    val list: List<Id> = listOf(Id(1), Id(2)) // boxed inside the list
    println(list.map { it.raw })
}

没有身份

值类没有稳定的引用身份。使用 === 进行引用相等性比较没有意义,而且值类不能用于对象身份很重要的场景,例如作为同步锁。

@JvmInline
value class Code(val value: Int)

fun main() {
    val a = Code(5)
    val b = Code(5)
    println(a == b)   // structural equality works
}

不能使用延迟初始化或属性委托

您不能对底层值应用 lateinit,值类也不支持对其唯一字段使用属性委托。该值必须在构造函数中设置。

@JvmInline
value class Slug(val value: String)

fun main() {
    val s = Slug("hello-world") // must be provided up front
    println(s.value)
}

JVM 名称修饰

在 JVM 上,接受值类参数的函数会在字节码中获得经过名称修饰的名称,以避免冲突。这会使 Java 互操作变得复杂;Java 调用方可能无法清晰地看到这些函数。

@JvmInline
value class Hz(val value: Int)

fun tune(freq: Hz) = freq.value

fun main() {
    println(tune(Hz(440))) // simple from Kotlin; mangled from Java
}

不适用于多字段包装器

如果您发现自己希望拥有两个属性,那么值类就不是合适的工具。请改用 data class,接受对象分配的开销,以换取更丰富的结构。

data class Coordinate(val lat: Double, val lng: Double)

fun main() {
    println(Coordinate(41.0, 29.0))
}

限制总结

值类不能:

  • 拥有超过一个属性
  • 拥有额外的幕后字段或使用 lateinit
  • 继承类或被类继承
  • 提供引用身份
  • 始终避免装箱

明智选择

对于单个、经过验证且类型安全的值,请使用值类。对于组合数据,请使用数据类。对于只为了提高可读性而不需要安全性的场景,请使用类型别名。每种工具都有适用之处。

快速检查

请检验您对值类限制的理解。

回顾

您学到了值类的限制:

  • 只能有一个属性,不能有额外的幕后字段
  • 不支持继承,也没有身份
  • 用于可空、泛型或接口场景时会重新发生装箱
  • JVM 名称修饰会使 Java 互操作变得复杂

请根据需求选择合适的工具。

常见问题解答

「限制」课时是免费的吗?

是的 — 「限制」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。

「限制」这节课中我会学到什么?

了解值类无法完成的操作 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Kotlin Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「限制」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Kotlin Academy 课中编写并运行代码吗?

能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 类型别名
  2. 内联值类
  3. 使用场景
  4. 限制
← 返回 Kotlin Academy