When writing code in Kotlin, you may encounter an error called “Variable must be initialized”.
This error occurs when, for example, you declare a variable and then try to use it without assigning a value to it.
In Kotlin, a variable is required to have a value when it is used, so an error occurs if the compiler determines that “a value may not have been assigned.”
This article introduces the main causes of the “Variable must be initialized” error in Kotlin and the basic ways to resolve it.
- What Is “Variable must be initialized”?
- Cause 1: Using a Variable Without Initializing It
- Cause 2: A Value May Not Be Assigned Depending on the Conditional Branch
- Initializing Directly Using an if Expression
- Cause 3: Assigning a Value Only in Some when Conditions
- Cause 4: A Class Property Has Not Been Initialized
- Initializing with a Constructor
- Initializing with an init Block
- Using lateinit
- Declaring It as a Nullable Type
- Whether to Use lateinit or a Nullable Type
- Points to Check When “Variable must be initialized” Appears
- Summary
What Is “Variable must be initialized”?
“Variable must be initialized” is an error that means that a variable needs to be initialized.
In Kotlin, simply declaring a local variable or another variable does not mean that you can freely use it. A value must be assigned before the variable is actually referenced.
fun main() {
var message: String
println(message)
}
In this example, a variable called message is declared, but it is used in println() without a value being assigned to it.
Therefore, the compiler determines that message does not contain a value and displays the “Variable must be initialized” error.
Cause 1: Using a Variable Without Initializing It
The most basic cause is declaring a variable and then using it without assigning a value to it.
fun main() {
var number: Int
println(number)
}
In this case, no value has been assigned to number.
You can resolve the error by setting an initial value when declaring the variable, as shown below.
fun main() {
var number: Int = 0
println(number)
}
If the type can be inferred, you can also omit the type declaration.
fun main() {
var number = 0
println(number)
}
Cause 2: A Value May Not Be Assigned Depending on the Conditional Branch
Even if it appears that a value is being assigned to a variable, an error may occur if there is a possibility that the value will not be assigned depending on a conditional branch.
fun main() {
val score = 80
var result: String
if (score >= 60) {
result = "Pass"
}
println(result)
}
In this code, a value is assigned to result if score >= 60 is true.
However, if the condition is not met, nothing is assigned to result. Therefore, the compiler determines that there is a possibility that no value exists when println(result) is executed.
In this case, add else so that a value is assigned under every condition.
fun main() {
val score = 80
var result: String
if (score >= 60) {
result = "Pass"
} else {
result = "Fail"
}
println(result)
}
Initializing Directly Using an if Expression
In Kotlin, if can be used as an expression, so the result of a conditional branch can be assigned directly to a variable.
fun main() {
val score = 80
val result = if (score >= 60) {
"Pass"
} else {
"Fail"
}
println(result)
}
With this approach, a value is always returned for either condition, making it easier to prevent initialization from being missed.
Cause 3: Assigning a Value Only in Some when Conditions
When using when, you also need to be careful with code in which a value is not assigned for every possibility.
fun main() {
val number = 2
var message: String
when (number) {
1 -> message = "One"
2 -> message = "Two"
}
println(message)
}
In this case, if number is anything other than 1 or 2, no value is assigned to message.
Add else so that a value is assigned in every case.
fun main() {
val number = 2
var message: String
when (number) {
1 -> message = "One"
2 -> message = "Two"
else -> message = "Other"
}
println(message)
}
Furthermore, using when as an expression allows you to write the code more concisely.
fun main() {
val number = 2
val message = when (number) {
1 -> "One"
2 -> "Two"
else -> "Other"
}
println(message)
}
Cause 4: A Class Property Has Not Been Initialized
Properties inside a class also generally need to be initialized when they are declared or through a constructor or another method.
class User {
var name: String
}
If a non-null String is declared without a value in this way, an error occurs because it has not been initialized.
The simplest solution is to set an initial value.
class User {
var name: String = ""
}
Initializing with a Constructor
It is also common for class properties to receive values from a constructor.
class User(val name: String)
fun main() {
val user = User("Taro")
println(user.name)
}
In this case, name is always set when an instance of User is created.
Initializing with an init Block
You can also use an init block when, for example, a property value is calculated when an instance is created.
class User(firstName: String, lastName: String) {
val fullName: String
init {
fullName = "$firstName $lastName"
}
}
Because a value is always assigned inside the init block, fullName can be used.
Using lateinit
In Android applications and similar cases, there are situations where a value cannot be set when a variable is declared and the variable must be initialized later.
In such cases, you can use lateinit.
lateinit var message: String
fun initialize() {
message = "Hello"
}
By adding lateinit, you can tell the compiler that “this variable will be initialized later.”
Note: Even when using lateinit, accessing the variable before actually assigning a value to it will cause an UninitializedPropertyAccessException.
Therefore, rather than adding lateinit simply to eliminate the error, it is important to make sure that the variable will always be initialized.
Declaring It as a Nullable Type
If the state in which a variable “does not yet have a value” has meaning in itself, another option is to declare it as a nullable type.
var message: String? = null
fun main() {
println(message)
}
Because String? is a type that allows null, you can set null as the initial value.
However, when using a nullable type, you need to take null into account in subsequent processing.
var message: String? = null
fun main() {
println(message?.length)
}
You can handle it using a safe call such as ?..
Whether to Use lateinit or a Nullable Type
lateinit and nullable types may be used in similar situations, but they have different meanings.
If “a value will definitely be assigned later, and you do not want to treat it as null after that,” lateinit may be appropriate.
On the other hand, if “the state in which no value exists is also a normal state,” using a nullable type is more natural.
Rather than changing a variable to lateinit or a nullable type simply to avoid an initialization error, it is important to choose based on what kind of state the variable is actually intended to have.
Points to Check When “Variable must be initialized” Appears
When “Variable must be initialized” appears, first check where the variable causing the error is declared and where that variable is first used.
- The variable was declared without assigning a value
- A value is assigned only in some
ifconditions - A value is assigned only in some
whenconditions - A class property does not have an initial value
- The variable is not initialized in a constructor or
initblock - The variable is designed to be initialized later, but
lateinitor a similar mechanism is not being used
In particular, when the code contains conditional branches, it is important to check not only whether “a value is assigned under the condition you expect,” but also whether a value is assigned on every execution path from the compiler’s perspective.
Summary
Kotlin’s “Variable must be initialized” error appears when a variable has not been assigned a value at the time it is used, or when there is a possibility that a value has not been assigned.
Basically, the error can be resolved by setting an initial value when declaring the variable or by ensuring that a value is assigned in every branch of if, when, and similar constructs.
For class properties, initialization can be performed using an initial value, a constructor, an init block, and similar methods. If a value needs to be set later, you can use lateinit or a nullable type depending on the design.
When the error appears, instead of looking only at the location of the error, check the processing from the variable declaration to where it is used, and verify whether “a value is always assigned by the time the variable is used.” This makes it easier to identify the cause.
