Nullable vs Non-Nullable in Kotlin: Key Differences and Usage
non-nullable types cannot hold null values, ensuring safety by default, while nullable types explicitly allow null by appending ? to the type. This distinction helps prevent common errors like null pointer exceptions by forcing developers to handle null cases safely.Quick Comparison
Here is a quick side-by-side comparison of nullable and non-nullable types in Kotlin.
| Aspect | Non-Nullable Type | Nullable Type |
|---|---|---|
| Syntax | String | String? |
| Can hold null? | No | Yes |
| Default behavior | Safe by default | Requires explicit handling |
| Accessing members | Direct access | Safe calls or checks needed |
| Compiler checks | Prevents null assignments | Allows null assignments |
| Common use case | Values that must exist | Values that might be missing |
Key Differences
Kotlin distinguishes between nullable and non-nullable types to improve code safety. A non-nullable type, like String, guarantees that the variable cannot hold a null value. This means the compiler enforces that you always assign a valid value, preventing null pointer exceptions at runtime.
On the other hand, a nullable type, written as String?, explicitly allows the variable to hold either a valid value or null. When working with nullable types, Kotlin requires you to handle the possibility of null using safe calls (?.), the Elvis operator (?:), or explicit null checks. This forces you to think about null safety and handle it properly.
In summary, non-nullable types provide safety by default, while nullable types offer flexibility but require careful handling to avoid runtime errors.
Code Comparison
Here is how you declare and use a non-nullable variable in Kotlin:
fun main() {
val name: String = "Alice"
println(name.length) // Safe to access length directly
// Uncommenting the next line causes a compile error:
// val errorName: String = null
}Nullable Equivalent
Here is how you declare and use a nullable variable in Kotlin, with safe handling:
fun main() {
val name: String? = null
// Safe call operator prevents crash if name is null
println(name?.length) // Prints: null
// Using Elvis operator to provide default value
val length = name?.length ?: 0
println(length) // Prints: 0
}When to Use Which
Choose non-nullable types when you are sure a value must always be present, like a username or an ID. This helps avoid null-related bugs and makes your code safer and easier to read.
Use nullable types when a value might be missing or unknown, such as optional user input or data from external sources. Always handle nullable values carefully with safe calls or null checks to prevent crashes.