Question
Kotlin Void vs Unit vs Nothing: Differences, Uses, and Examples
Question
Kotlin has three types that appear similar at first glance:
VoidUnitNothing
They can seem comparable to JavaScript concepts such as null, undefined, and void 0, which raises the question of whether they overlap unnecessarily.
What is each of these Kotlin types used for, and how do they differ in meaning and behavior?
Short Answer
By the end of this page, you will understand what Void, Unit, and Nothing mean in Kotlin, when each one appears, and why they are not interchangeable. You will also learn how these types are used in function return types, Java interoperability, and expressions that never complete normally.
Concept
Kotlin uses Unit, Nothing, and sometimes Void for different purposes, even though they can look related.
Unit
Unit is Kotlin's way of saying:
"This function finishes normally, but it does not return any useful value."
It is similar to Java's void, but with one important difference: Unit is a real type in Kotlin. It has exactly one value: Unit.
fun printMessage(): Unit {
println("Hello")
}
In most Kotlin code, you omit it:
fun printMessage() {
println("Hello")
}
Kotlin still treats that function as returning Unit.
Nothing
Nothing means:
"This code never successfully produces a value because it never completes normally."
A function returning Nothing might:
- always throw an exception
- enter an infinite loop
- terminate the program
Example:
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
This function never returns to the caller.
Nothing is useful in the type system because it tells Kotlin that execution stops here.
Void
Void is not the usual Kotlin choice. It mainly exists for Java interoperability.
In Java, Void is a class type (java.lang.Void), while void is a primitive-like return concept. Kotlin may use Void when interacting with Java APIs that explicitly mention Void.
Example context:
- Java generic APIs like
Callable<Void> - frameworks or libraries written in Java
In idiomatic Kotlin, you usually use Unit, not Void.
Why this matters
These types help Kotlin express intent more precisely:
Unit: normal completion, no meaningful resultNothing: no completion at allVoid: Java interop type, usually avoid in pure Kotlin
This precision improves readability, compiler checks, and interoperability with Java libraries.
Mental Model
Think of a function like a delivery trip.
Unitmeans: the driver came back, but there was no package to deliver.Nothingmeans: the driver never comes back at all.Voidmeans: you are working with another company's paperwork system (Java), and they use a special form namedVoid.
So even though all three may look like "no value," they describe very different situations:
- one finishes normally
- one never finishes normally
- one mostly exists to match Java APIs
Syntax and Examples
Core syntax
Unit
fun log(message: String): Unit {
println(message)
}
Usually written without the explicit return type:
fun log(message: String) {
println(message)
}
Nothing
fun crash(): Nothing {
throw RuntimeException("Something went wrong")
}
Void
fun javaStyle(): Void? {
return null
}
This is uncommon in Kotlin and usually only appears when matching Java APIs.
Beginner-friendly examples
Example 1: Unit
fun greet(name: String) {
println("Hello, $name")
}
This function does work and ends normally. It returns Unit.
Example 2: Nothing
fun missingUser(): Nothing {
throw IllegalStateException("User not found")
}
This function never returns a result because it always throws.
Example 3: Void in interop situations
val task: java.util.concurrent.Callable<Void> = java.util.concurrent.Callable {
println("Running task")
null
}
Here, Void is used because the Java interface expects it.
A useful expression example
Because throw has type Nothing, it can be used where another type is expected:
fun getName(name: String?): String {
return name ?: throw IllegalArgumentException("Name is required")
}
The right side of ?: is Nothing, so Kotlin accepts it as part of an expression that must produce a String.
Step by Step Execution
Consider this example:
fun getUsername(input: String?): String {
return input ?: throw IllegalArgumentException("Username cannot be null")
}
Now trace it.
Case 1: input is not null
getUsername("alice")
Step by step:
- The function receives
"alice". - Kotlin checks
input ?: .... - Since
inputis notnull, the left side is used. - The function returns
"alice". - The function completes normally.
Case 2: input is null
getUsername(null)
Step by step:
- The function receives
null. - Kotlin checks
input ?: .... - Since
inputisnull, Kotlin evaluates the right side. - The right side throws
IllegalArgumentException. - The function does not return a
Stringvalue. - Execution stops at that point.
The key idea is that throw has type Nothing, so Kotlin knows there is no normal return path there.
Now compare with Unit:
fun printUsername(input: String?) {
println(input ?: "guest")
}
Step by step:
- The function prints either the provided username or
"guest". - It finishes normally.
- It returns
Unit.
So:
Unit= completed normallyNothing= never completed normally
Real World Use Cases
Where Unit is used
Unit appears in functions that perform actions:
- logging
- printing output
- saving data
- sending analytics events
- updating UI state
- writing files
Example:
fun saveUser(user: User) {
repository.save(user)
}
The function does something useful, but there is no meaningful value to return.
Where Nothing is used
Nothing is common in code paths that must stop execution:
- validation failures
- impossible states
- helper functions that always throw
- program termination wrappers
Example:
fun requireAdmin(isAdmin: Boolean): Nothing {
throw IllegalAccessException("Admin access required")
}
A more realistic pattern is a helper used conditionally:
fun unauthorized(): Nothing {
throw IllegalStateException("Unauthorized")
}
Then:
val user = currentUser ?: unauthorized()
Where Void is used
Void shows up mostly when Kotlin talks to Java libraries:
- Java generics
- callback APIs
- old framework interfaces
- executor tasks returning no meaningful value
Example:
val callable = java.util.concurrent.Callable<Void> {
println("Background work")
null
}
Real Codebase Usage
In real Kotlin projects, developers usually follow these patterns.
Unit for side-effect functions
Most application code uses Unit implicitly:
fun updateProfile(profile: Profile) {
validate(profile)
api.save(profile)
}
This is the normal choice for command-style functions.
Nothing for guard clauses and fail-fast code
A common pattern is writing helper functions that stop execution:
fun failValidation(message: String): Nothing {
throw IllegalArgumentException(message)
}
Then using them inside expressions:
val email = inputEmail ?: failValidation("Email is required")
This is especially useful for:
- validation
- null checking
- impossible branches
- exhaustive
whenhandling
Nothing and unreachable code
Developers use Nothing to signal that a branch cannot continue:
fun parseRole(role: String): String = when (role) {
"admin" -> "Administrator"
"user" -> "Standard User"
else -> throw IllegalArgumentException("Unknown role")
}
The else branch has type Nothing, which fits because it never returns normally.
Void only when interop requires it
In production Kotlin code, Void is typically avoided unless a Java API demands it.
For example:
val futureTask = java.util.concurrent.Callable<Void> {
doCleanup()
null
}
If you are writing Kotlin-first APIs, prefer Unit over Void.
Practical rule used by teams
- Use
Unitfor ordinary no-result functions. - Use
Nothingfor code that always throws or never ends. - Use
Voidonly to match Java types.
Common Mistakes
1. Using Void instead of Unit in Kotlin code
Broken style:
fun logMessage(): Void? {
println("Hello")
return null
}
Better:
fun logMessage() {
println("Hello")
}
Why this is a mistake:
Voidis not idiomatic Kotlin- it often forces
null - it makes APIs less natural
2. Thinking Unit means null
Unit is a real value, not the same as null.
val result: Unit = Unit
null means absence of a value. Unit means a specific no-useful-result value.
3. Thinking Nothing is the same as "returns nothing"
Broken understanding:
fun test(): Nothing {
println("Hi")
}
This is invalid because the function completes normally.
Correct usage:
fun test(): Nothing {
throw IllegalStateException("Stops here")
}
4. Returning null for Nothing
Broken code:
fun bad(): Nothing {
return null
}
This is impossible. Nothing has no values.
5. Forgetting that throw is an expression of type Nothing
Many beginners write extra code because they do not realize this:
Less clean:
fun getId(id: String?): String {
if (id == null) {
throw IllegalArgumentException("Missing id")
}
return id
}
Also valid, but Kotlin often allows a shorter expression form:
fun getId(id: String?): String {
return id ?: throw IllegalArgumentException("Missing id")
}
6. Confusing Java void with Java Void
In Java:
voidis a return-only conceptVoidis a class type
In Kotlin, Unit usually maps to the no-result function case, while Void appears mainly for interop.
Comparisons
| Concept | What it means | Can it have a value? | Normal Kotlin use | Typical example |
|---|---|---|---|---|
Unit | Function completes normally with no meaningful result | Yes, exactly one value: Unit | Very common | fun log() { ... } |
Nothing | Function never completes normally | No | Used for throw, infinite loops, fail-fast helpers | fun fail(): Nothing { throw ... } |
Void | Java interop type (java.lang.Void) | Practically used as null when nullable | Rare in Kotlin | Callable<Void> |
Unit vs Nothing
| Feature | Unit | Nothing |
|---|---|---|
| Function can finish normally | Yes | No |
| Has a value | Yes (Unit) | No |
| Used for side-effect functions | Yes | No |
| Used for always-throwing functions | No | Yes |
Unit vs Void
| Feature | Unit | Void |
|---|---|---|
| Idiomatic Kotlin | Yes | No |
| Real Kotlin type | Yes | Java interop type |
| Common in pure Kotlin APIs | Yes | Rare |
Often requires null | No | Yes, when nullable |
Quick rule
- If your function just does work, use
Unit. - If your function never returns, use
Nothing. - If a Java API forces the type, use
Void.
Cheat Sheet
Quick reference
Unit
- Means: no meaningful return value
- Function completes normally
- Kotlin's usual replacement for Java
void - Has one value:
Unit - Usually omitted in function declarations
fun printName() {
println("Sam")
}
Nothing
- Means: no value can ever be returned
- Function never completes normally
- Used for
throw, fatal errors, infinite loops - Has no values
fun fail(): Nothing {
throw IllegalStateException("Failed")
}
Void
- Means: Java interop type
java.lang.Void - Rare in Kotlin-first code
- Mostly used in Java generic APIs
- Often appears as
Void?withnull
val task: java.util.concurrent.Callable<Void> = java.util.concurrent.Callable {
null
}
Rules to remember
- Prefer
Unitin Kotlin APIs. - Use
Nothingwhen execution cannot continue. - Use
Voidonly when Java libraries require it. Unitis notnull.Nothinghas no instances.throwhas typeNothing.
Common patterns
val name = input ?: throw IllegalArgumentException("Name required")
fun logEvent() = println("saved")
fun unreachable(): Nothing = throw IllegalStateException("Impossible state")
FAQ
What is the difference between Unit and Nothing in Kotlin?
Unit means a function finishes normally but has no meaningful result. Nothing means a function never finishes normally, such as one that always throws an exception.
Is Kotlin Unit the same as Java void?
They are similar in purpose, but not identical. Unit is a real type with one value, while Java void is not a normal type you can use as a value.
When should I use Void in Kotlin?
Usually only when working with Java APIs that explicitly require Void, especially generic types like Callable<Void>.
Why does throw work inside expressions in Kotlin?
Because throw has type Nothing. Kotlin knows that branch never returns, so it can fit into expressions expecting another type.
Can a function returning Nothing return null?
No. Nothing has no values at all, including null.
Should I write : Unit explicitly in Kotlin functions?
Usually no. Kotlin developers normally omit it unless writing it improves clarity.
Is Void the same as Unit in Kotlin?
No. Unit is the normal Kotlin type for no meaningful result. Void is mainly a Java interop type.
Can Nothing be useful with nullable values?
Yes. It is often used in Elvis expressions like value ?: throw ..., where the failure branch never returns.
Mini Project
Description
Build a small Kotlin validation utility that demonstrates all three concepts: a normal action function using Unit, a fail-fast helper using Nothing, and a Java interop example using Void. This project mirrors real application code where you validate input, log progress, and sometimes connect to Java libraries.
Goal
Create a small program that validates a username, logs a success message, and includes a Java Callable<Void> task.
Requirements
- Create a function that prints a log message and returns normally.
- Create a function that always throws an exception for invalid input.
- Create a function that validates a nullable username using the Elvis operator.
- Add a Java
Callable<Void>example that performs an action and returnsnull.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.