Type safety
- Kotlin course
- Intermediate
- Lesson 77/116
- 5 min
Learn type safety with value classes.
Type safety
The core purpose of a value class is type safety. UserId and OrderId both wrap a String yet they are distinct types. A declaration like fun findUser(id: UserId) makes passing an OrderId by mistake a compile error.
Using the same String type everywhere is error-prone: if a function expects both a user and an order number the compiler cannot tell which one you passed. A value class removes this risk. There is no runtime memory cost; the check happens only at compile time.
Runtime representation
A value class is represented at runtime without boxing. UserId("U1") is stored in memory simply as the String "U1"; no wrapper object is created. This gives the value class zero overhead.
Boxing can occur when a value class is assigned to an Any or added to a generic collection. In these rare cases a value class is still less overhead than a wrapper class. In most uses a value class is as fast as a String but provides type safety.
Practice Type safety with UserId and OrderId
Define @JvmInline value class UserId(val id: String) and @JvmInline value class OrderId(val id: String). Write fun findUser(id: UserId) = println("User: ${id.id}"). In main call findUser(UserId("U1")).
Starter code
// Define the UserId and OrderId value classes
// Write a findUser(id: UserId) method
fun main() {
// Pass a UserId instance to findUser
}Sample solution
@JvmInline
value class UserId(val id: String)
@JvmInline
value class OrderId(val id: String)
fun findUser(id: UserId) = println("User: ${id.id}")
fun main() {
findUser(UserId("U1"))
}Expected output
User: U1
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Complete the findUser signature
fun findUser(id: ____) { /* ... */ }
fun findUser(id: UserId) { /* ... */ }
Explanation: findUser accepts only UserId.
2 Match the type safety concepts
| Term | Meaning |
|---|---|
UserId vs String |
Distinct types |
no boxing |
Zero overhead |
compile-time |
Compile check |
runtime |
Underlying type |
3 Why use a value class instead of String?
- It runs faster
- It needs less code
- It uses less memory
- It provides type safety Correct answer
Explanation: A value class turns type mix-ups into compile errors.