限制
了解值类无法完成的操作
限制 是 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 反馈 — 无需本地设置。