在 Kotlin 中,可以使用 value class
(值类)为原始类型(如 Int
、String
等)提供类型安全的包装,从而避免混淆不同语义的标识符(如 EmployeeId
和 CustomerId
)。
Kotlin 值类的核心特性
- 类型安全
将原始值包装为独立的类型,编译器会将其视为不同的类型,直接替换会导致编译错误。 - 零运行时开销
在大多数情况下,Kotlin 会将值类内联为原始类型,避免对象创建的开销(仅在需要时才装箱,例如存入集合)。 - 轻量级语法
使用value class
关键字定义,语法简洁。
示例:避免混淆 EmployeeId
和 CustomerId
// 定义两个值类,包装 Int 类型的 ID
@JvmInline
value class EmployeeId(val id: Int)
@JvmInline
value class CustomerId(val id: Int)
// 使用示例
fun getEmployee(id: EmployeeId) { /* ... */ }
fun getCustomer(id: CustomerId) { /* ... */ }
fun main() {
val employeeId = EmployeeId(1001)
val customerId = CustomerId(2001)
getEmployee(employeeId) // ✅ 编译通过
getEmployee(customerId) // ❌ 编译错误:Type mismatch. Required: EmployeeId, Found: CustomerId
}
关键优势
- 编译时错误
混淆EmployeeId
和CustomerId
时,编译器直接报错,而非等到运行时。 - 避免原始类型滥用
解决“原始类型偏执”(Primitive Obsession)问题,提升代码语义。 - 性能优化
值类在运行时通常被优化为原始类型,除非需要装箱(例如存入List<Any>
)。
注意事项
- JVM 兼容性
使用@JvmInline
注解确保与 Java 互操作性(Kotlin 1.5+ 支持)。 - 限制条件
值类只能包装单个值,且不能继承或被继承。
通过 Kotlin 的值类,可以将潜在的逻辑错误转化为编译错误,同时保持高性能和代码可读性。