英文:
Can't initialize variables inside of when statement in Kotlin
问题
由于某种原因,我的Kotlin程序不会初始化在when语句内赋值的变量。以下是代码:
import kotlin.random.Random
import kotlin.random.nextInt
val mood: String
when(Random.nextInt(1..2)) {
1 -> {
mood = "loud"
println("$mood")
}
2 -> {
mood = "quiet"
println("$mood")
}
}
println("$mood")
在when语句内的行会被打印,但当我运行最后一行时,我会收到一个“变量'mood'必须被初始化”错误。
我不知道我可能在这里做错了什么...
英文:
For whatever reason, my Kotlin program won't initialize variables assigned inside a when statement. Here's the code:
import kotlin.random.Random
import kotlin.random.nextInt
val mood: String
when(Random.nextInt(1..2)) {
1 -> {
mood = "loud"
println("$mood")
}
2 -> {
mood = "quiet"
println("$mood")
}
}
println("$mood")
The lines inside the when statement are printed, but when I run the last line, I get a "Variable 'mood' must be initialized" error.
I don't know what I could possibly be doing wrong here...
答案1
得分: 3
这是一个编译错误,而不是执行错误。
从编译器的角度来看,您的 when
语句不是穷尽的,因为一个 Int
可能不仅仅是 1 或 2。实际上,nextInt(1..2)
只返回这些数字的事实并没有被编译器考虑在内,编译器只关注类型。
要解决这个问题,您应该添加一个 else
语句,在其中也初始化 mood
,例如:
val mood: String
when (Random.nextInt(1..2)) {
1 -> {
mood = "loud"
println(mood)
}
2 -> {
mood = "quiet"
println(mood)
}
else -> {
mood = "currently impossible"
}
}
println(mood)
或者,您可以使用常规的 var
或 lateinit var
代替 val
。
要么直接初始化一个常规变量:
var mood: String = ""
要么使用 lateinit var
:
lateinit var mood: String
在后一种情况下,编译器无法再确保初始化(这实际上是为什么在您的代码中首次出现警告的原因)。
此外,如果您希望在初始化后强制 mood
为只读,这两种方法可能都不太合适。
英文:
This is a compilation error, not an execution one.
Your when
statement is not exhaustive from the compiler point of view because an Int
can be more than just 1 or 2. The fact that, in practice, nextInt(1..2)
only returns those numbers is not taken into account by the compiler, which is looking at the type.
To solve the issue you should add an else statement where you also initialize mood
, e.g.:
val mood: String
when (Random.nextInt(1..2)) {
1 -> {
mood = "loud"
println(mood)
}
2 -> {
mood = "quiet"
println(mood)
}
else -> {
mood = "currently impossible"
}
}
println(mood)
Alternatively you can use a regular var
or lateinit var
instead of a val
.
Either you initialize a regular var directly:
var mood: String = ""
Or use a lateinit var:
lateinit var mood: String
In the latter case, the compiler can't ensure initialization anymore (which is actually why it's complaining in the first place in you code).
Also, both of these might be not desiderable if you want to enforce mood
to be read-only after initialization.
答案2
得分: 0
在Kotlin中,使用关键字val声明的变量必须在声明点或类的构造函数中进行初始化。在你的代码中,mood变量没有被赋予初始值,而你试图在when语句内部为它赋值。然而,编译器无法确定在运行时是否会执行任何一个分支,因此它不会将变量视为完全初始化。
要解决这个问题,你可以将mood变量声明为var而不是val,或者在声明时为它赋予初始值。以下是使用var修复此问题的代码版本:
import kotlin.random.Random
import kotlin.random.nextInt
var mood: String
when (Random.nextInt(1..2)) {
1 -> {
mood = "loud"
println("$mood")
}
2 -> {
mood = "quiet"
println("$mood")
}
}
println("$mood")
通过使用var而不是val,你表明这个变量可以在以后重新赋值。由于mood变量在when语句的两个分支中都被赋值,编译器不再抱怨它未初始化。
请注意,when分支的顺序应该覆盖所有可能的情况,否则你可能会遇到“when表达式必须是穷尽的”警告。在你的情况下,nextInt的范围是1到2,因此这两个分支应该足够了。
英文:
In Kotlin, variables declared with the val keyword must be initialized at the point of declaration or in the constructor of the class. In your code, the mood variable is declared without an initial value, and you are trying to assign values to it inside the when statement. However, the compiler is unable to determine if either of the branches will be executed at runtime, so it doesn't consider the variable as fully initialized.
To fix this issue, you can either declare the mood variable as a var instead of a val or assign an initial value to it when declaring it. Here's an updated version of your code using a var:
import kotlin.random.Random
import kotlin.random.nextInt
var mood: String
when (Random.nextInt(1..2)) {
1 -> {
mood = "loud"
println("$mood")
}
2 -> {
mood = "quiet"
println("$mood")
}
}
println("$mood")
By using a var instead of a val, you indicate that the variable can be reassigned later. Since the mood variable is assigned within both branches of the when statement, the compiler no longer complains about it being uninitialized.
Note that the order of the when branches should cover all possible cases, otherwise you might encounter a "when expression must be exhaustive" warning. In your case, the range of nextInt is 1 to 2, so the two branches should be sufficient.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论