![](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhSYZt%2FbtsFOZeOLPL%2FZ0PauVlLR8zYbJWkFNYbo1%2Fimg.png)
If I can use if, when to use when
DoDoBest
·2024. 3. 6. 12:57
Kotlin 공식문서에서도 if 대신 when을 사용할 것을 권장하고 있습니다.
그런데 왜 if 대신 when을 사용해야 하는지 아시나요?
Prefer using when if there are three or more options.
https://kotlinlang.org/docs/coding-conventions.html#if-versus-when
Coding conventions | Kotlin
kotlinlang.org
Kotlin의 when은 Java의 switch 문으로 변환된다.
Kotlin에서 when을 사용하는 코드는 Java의 switch 문으로 변환됩니다. 직접 확인해봅시다.
아래와 같이 사용자가 입력한 값에 따라 Grade를 반환하는 함수가 있습니다.
enum class Grade {
FirstFreshman, FirstSophomore, FirstJunior, FirstSenior,
SecondFreshman, SecondSophomore, SecondJunior, SecondSenior,
}
fun checkWithWhen(age: Int): Grade {
return when (age) {
90 -> Grade.FirstSenior
80 -> Grade.FirstJunior
70 -> Grade.FirstSophomore
60 -> Grade.FirstFreshman
50 -> Grade.SecondSenior
40 -> Grade.SecondJunior
30 -> Grade.SecondSophomore
else -> Grade.SecondFreshman
}
}
Kotlin Bytecode를 Java로 디컴파일된 코드를 살펴보면, switch 문으로 바뀐 것을 확인할 수 있습니다.
Switch 문의 특징
컴파일러가 switch 문을 컴파일 할 때, 각 case의 constant를 확인한 후, Jump Table을 생성합니다.
Jump Table은 case에 해당하는 값을 Key, case에 해당하는 코드가 존재하는 메모리 주솟값을 value로 가지는 Map입니다. 만약 1,2,3,4,5와 같이 Case가 붙어 있는 경우 List로 생성하기도 합니다.
If-else 문은 조건식을 모두 비교하기에 O(n)이 걸립니다.
switch 문은 jumpTable[caseNum]과 같이 실행해야 하는 코드를 바로 알 수 있기에 O(1)이 걸립니다.
Switch 문은 if-else보다 얼마나 빠를까?
if-else 문과 when 문으로 실행한 후 걸리는 시간을 측정해서 비교해봤습니다.
10,000,000,000번 반복한 결과
if-else : 2243, 2250, 2242, 2197
when : 2236, 2228, 2230, 2191
100,000,000,000번 반복한 결과
if-else : 22237, 22357, 22464, 22001
when : 21873, 21803, 21803, 22279
enum class Grade {
FirstFreshman, FirstSophomore, FirstJunior, FirstSenior,
SecondFreshman, SecondSophomore, SecondJunior, SecondSenior,
}
fun main() {
val age = 40
val st = System.currentTimeMillis()
for (i in 0 until 10_000_000_000) {
checkWithIf(age)
}
val timeOfIf = System.currentTimeMillis() - st
val st2 = System.currentTimeMillis()
for (i in 0 until 10_000_000_000) {
checkWithWhen(age)
}
val timeOfWhen = System.currentTimeMillis() - st2
println("If 소요 시간: $timeOfIf") // 2243, 2250, 2242, 2197
println("When 소요 시간: $timeOfWhen") // 2236, 2228, 2230, 2191
}
fun checkWithIf(age: Int): Grade {
return if (age == 90) {
Grade.FirstSenior
} else if (age == 80) {
Grade.FirstJunior
} else if (age == 70) {
Grade.FirstSophomore
} else if (age == 60) {
Grade.FirstFreshman
} else if (age == 50) {
Grade.SecondSenior
} else if (age == 40) {
Grade.SecondJunior
} else if (age == 30) {
Grade.SecondSophomore
} else {
Grade.SecondFreshman
}
}
fun checkWithWhen(age: Int): Grade {
return when (age) {
90 -> Grade.FirstSenior
80 -> Grade.FirstJunior
70 -> Grade.FirstSophomore
60 -> Grade.FirstFreshman
50 -> Grade.SecondSenior
40 -> Grade.SecondJunior
30 -> Grade.SecondSophomore
else -> Grade.SecondFreshman
}
}
When의 또다른 장점
when은 exhaustive하다는 특징이 있습니다. if 문은 else문에 도달하지 않는 것이 분명함에도 else가 강제되는 경우가 있습니다.
반면 when은 enum, sealed를 이용할 경우 else를 붙이지 않아도 됩니다.
enum class LastName {
Kim, Lee
}
fun main() {
val lastName = LastName.Kim
generateNameWithIf(lastName)
generateNameWithWhen(lastName)
}
fun generateNameWithIf(lastNam: LastName): String {
return if (lastNam == LastName.Lee) {
"이민수"
} else if (lastNam == LastName.Kim) {
"김민수"
} else { // else block이 필수
"미지정"
}
}
fun generateNameWithWhen(lastNam: LastName): String {
return when (lastNam) {
LastName.Lee -> "이민수"
LastName.Kim -> "김민수"
}
}
다음과 같이 조건식에 모든 경우를 포함하더라도, when 절은 else 구문을 강제합니다.
when 절에서 else 구문을 없애려면 sealed, enum을 활용해야 함을 알 수 있습니다.
fun getGrade(age: Int): String {
return when(age) { // 'when' expression must be exhaustive, add necessary 'else' branch
in Int.MIN_VALUE until 0 -> "Bad"
in 0 until 30 -> "Good"
in 30 .. Int.MAX_VALUE -> "Excellent"
}
}
참고자료
https://www.geeksforgeeks.org/switch-vs-else/
switch vs if else - GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
www.geeksforgeeks.org
https://thuc.space/posts/jump_table/
Thuc notes - Jump table (branch table)
The jump table is a method to transfer program control to another code block using a table of branch or jump instructions.
thuc.space
From the C_Programming community on Reddit
Explore this post and more from the C_Programming community
www.reddit.com
'학습 > CS' 카테고리의 다른 글
Sealed class vs Sealed interface vs Enum (0) | 2024.03.05 |
---|---|
Kotlin에서 data class는 왜 사용할까 (0) | 2024.02.16 |