PC パソコン

Causes and Solutions for Kotlin “Val cannot be reassigned”

When writing code in Kotlin, you may encounter an error called “Val cannot be reassigned”.

This error occurs when, for example, you try to assign a different value later to a variable declared with val.

In Kotlin, once a value has been assigned to a variable declared with val, it cannot be reassigned. Therefore, if you need to change the value, you need to declare the variable according to its intended use, such as by using var.

This article introduces the main causes of the “Val cannot be reassigned” error in Kotlin and the basic ways to resolve it.

What Is “Val cannot be reassigned”?

“Val cannot be reassigned” is an error that means that a val cannot be reassigned.

In Kotlin, you use val or var when declaring a variable.

Once a value has been assigned to a val, another value cannot be reassigned to it. On the other hand, a var can be changed later.

fun main() {
    val number = 10

    number = 20
}

In this example, after declaring number with val, the code tries to reassign 20 to it.

Because a val cannot be reassigned, the “Val cannot be reassigned” error is displayed.

Cause 1: Reassigning a Variable Declared with val

The most basic cause is assigning a different value later to a variable declared with val.

fun main() {
    val message = "Hello"

    message = "Goodbye"
}

In this case, "Hello" is initially assigned to message.

An error occurs because the code then tries to assign "Goodbye".

If you need to change the value, declare it with var instead of val.

fun main() {
    var message = "Hello"

    message = "Goodbye"

    println(message)
}

A variable declared with var can be assigned a different value later.

Difference Between val and var

In Kotlin, you use val and var differently depending on whether the value of the variable needs to be changed.

val name = "Taro"
var age = 20

age = 21

Because name is declared with val, another string cannot be reassigned to it.

On the other hand, because age is declared with var, its value can be changed from 20 to 21.

If a value does not need to be changed, using val as a general rule makes it easier to prevent unintended reassignment.

Cause 2: Reassigning a val Inside a Conditional Branch

An error also occurs if you reassign a val that already has a value inside a conditional branch such as if.

fun main() {
    val result = "Undetermined"
    val score = 80

    if (score >= 60) {
        result = "Pass"
    }
}

In this code, result is initialized with "Undetermined" when it is declared.

An error occurs because the code then tries to reassign "Pass" inside the if statement.

If the design requires the value to be changed, use var.

fun main() {
    var result = "Undetermined"
    val score = 80

    if (score >= 60) {
        result = "Pass"
    }

    println(result)
}

Assigning Directly to a val Using an if Expression

If the value does not need to be changed midway and you only want to determine the initial value based on a condition, you can use if as an expression.

fun main() {
    val score = 80

    val result = if (score >= 60) {
        "Pass"
    } else {
        "Fail"
    }

    println(result)
}

With this approach, the result of the condition becomes the initial value of result directly.

Therefore, there is no need to change result to var and reassign it later.

Cause 3: Reassigning a val Inside when

The same error occurs if you try to assign another value inside when to a val that has already been initialized.

fun main() {
    val message = "Unknown"
    val number = 1

    when (number) {
        1 -> message = "One"
        2 -> message = "Two"
    }
}

In this case, "Unknown" has already been assigned to message, so it cannot be reassigned inside when.

If the value needs to be changed, use var.

fun main() {
    var message = "Unknown"
    val number = 1

    when (number) {
        1 -> message = "One"
        2 -> message = "Two"
    }

    println(message)
}

Initializing Using a when Expression

Because when can also be used as an expression, if you only need to determine a value based on a condition, you can use it directly when initializing a val.

fun main() {
    val number = 1

    val message = when (number) {
        1 -> "One"
        2 -> "Two"
        else -> "Unknown"
    }

    println(message)
}

With this method, there is no need to reassign message, so it can remain a val.

Cause 4: Trying to Update a val Inside a Loop

If you try to change a value during repeated processing, it cannot be reassigned if it is declared with val.

fun main() {
    val count = 0

    for (i in 1..5) {
        count = count + 1
    }
}

In this code, the value of count is being changed each time the loop runs.

Because the value needs to be updated repeatedly, use var.

fun main() {
    var count = 0

    for (i in 1..5) {
        count = count + 1
    }

    println(count)
}

You can also use the increment operator as shown below.

fun main() {
    var count = 0

    for (i in 1..5) {
        count++
    }

    println(count)
}

The Contents of an Object May Still Be Changed Even with val

Rather than meaning that “the value itself cannot be changed,” val means that the object referenced by the variable cannot be reassigned to a different one.

Therefore, if a mutable object is held in a val, it may be possible to change the internal state of that object.

fun main() {
    val numbers = mutableListOf(1, 2, 3)

    numbers.add(4)

    println(numbers)
}

In this case, numbers itself is declared with val, but the contents of the MutableList can be changed.

On the other hand, another list cannot be reassigned to numbers.

fun main() {
    val numbers = mutableListOf(1, 2, 3)

    numbers = mutableListOf(4, 5, 6)
}

In this case, “Val cannot be reassigned” occurs because the code is trying to reassign a different object to numbers.

Declaring something with val does not necessarily mean that the referenced object itself becomes immutable. What val prohibits is reassigning a different value or a different reference to that variable.

When Reassigning a val Property

If a class property is declared with val, it also cannot be changed to a different value after initialization.

class User {
    val name = "Taro"

    fun changeName() {
        name = "Jiro"
    }
}

In this case, name has already been initialized as a val, so it cannot be reassigned inside changeName().

If the property value needs to be changed later, declare it with var.

class User {
    var name = "Taro"

    fun changeName() {
        name = "Jiro"
    }
}

Changing val to var Is Not Always the Right Solution

When “Val cannot be reassigned” appears, changing val to var may eliminate the error itself.

However, if even values that do not actually need to be changed are declared with var, they may be modified unintentionally elsewhere.

If you only need to determine a value based on a condition, it is also important to check whether you can initialize the val with the appropriate value from the beginning by using an if expression or a when expression.

As a general rule, use var when the value needs to be changed later, and use val when the value does not need to be changed after initialization.

Points to Check When “Val cannot be reassigned” Appears

When “Val cannot be reassigned” appears, check whether the variable causing the error is declared with val or var.

  • Are you reassigning a different value to a variable declared with val?
  • Are you reassigning it inside if or when?
  • Are you trying to update the value inside a loop?
  • Are you trying to change a class val property later?
  • If the design requires the value to change, should you be using var?
  • Can you initialize it with an if expression or when expression without reassigning it?

Rather than simply changing val to var, checking whether the variable really needs to be changed midway allows you to make a more appropriate correction.

Summary

Kotlin’s “Val cannot be reassigned” error appears when you try to assign a different value to a variable declared with val after it has been initialized.

If the value needs to be changed later, declaring it with var allows it to be reassigned.

On the other hand, if you only need to determine the initial value based on a condition, you can use an if expression or a when expression to write the code without reassigning the val.

Also, with a mutable object held in a val, it may be possible to change the contents inside the object, but a different object cannot be reassigned to the variable itself.

When the error appears, before simply changing the variable to var, it is important to check whether the value really needs to be changed and to use val and var appropriately according to their purpose.