Kotlin 예외 처리 (try, catch, finally)

예외의 기본

Kotlin 예외 처리에는 Java와 동일하게 try, catch, finally 키워드를 사용한다.

다음은 NumberFormatException 예외를 처리하는 예이다.

try {
    val num = "abc".toInt()
} catch (e : NumberFormatException) {
    System.err.println(e)
}

Output:

java.lang.NumberFormatException: For input string: "abc"

예외를 던지는 것도 Java와 동일하게 throw를 사용한다. 클래스의 인스턴스를 생성할 때 new가 필요 없었던 것처럼, 여기에서도 new는 필요 없다.

fun fibonacci(n: Int) {
    if (n < 0) throw IllegalArgumentException("음수는 지정할 수 없습니다.")
    // ...
}

Output:

java.lang.IllegalArgumentException: 음수는 지정할 수 없습니다.

예외 잡는건 필수가 아니다.

Java에서는 IOException 등 검사 예외(checked exception)를 던지는 메서드를 호출하는 함수는 반드시 catch로 예외를 잡거나, 자신의 함수에서 throws IOException을 선언해야 했다. Kotlin에서는 검사 예외(checked exception)와 비검사 예외(unchecked exception)를 구분하지 않으므로, 함수에 throws IOException을 선언할 필요가 없다. 던져진 예외를 잡을지 말지는 호출자의 자유이다. 잡히지 않은 예외는 호출자의 함수에 전파된다.

fun throwIoException() {
    throw IOException("로딩 에러!")
}

fun foo() {
    // IOException을 던지는 함수를 호출하고 있지만,
    // 이 foo 메서드에서는 throws 선언을 하지 않아도 된다.
    throwIoException()
}

fun main() {
    try {
        foo()
    } catch (e : IOException) {
        System.err.println(e)
    }
}

try를 식으로 사용할 수 있다.

Kotlin에서는 try도 표현식이다. try 블록에서 결과 값을 그대로 변수로 받거나 함수의 반환값으로 반환할 수 있다.

아래 예에서는 try 블록에서 실행한 String.toInt()의 결과를 num 변수에 대입하고 있다.

fun printIfInt(s: String) {
    val num = try {
        s.toInt()
    } catch (e: NumberFormatException){
        return
    }
    println(num)
}

Java에서는 try 블록 안에서 생성한 객체를 블록 밖에서 참조하려면 블록 밖에서 해당 변수를 정의해 두어야 했다(일단 null 값을 넣는 등). Kotlin에서는 그런 번거로운 작업을 하지 않아도 된다.

위 예제에서는 예외가 발생하면 return으로 함수에서 바로 빠져나가도록 했지만, 삼항 연산자처럼 다른 값을 반환할 수도 있다. 다음 예제에서는 문자열을 제대로 구문 분석하지 못한 경우 num 변수에 null을 저장하도록 하고 있다.

val num = try {
    s.toInt()
} catch (e: NumberFormatException){
    null
}

물론 이 예시와 같은 처리는 String.toIntOrNull이라는 함수를 사용하는 것이 맞을 것이다.

val num = s.toIntOrNull();  // Int로 변환할 수 없는 경우 null로 변환한다.

추가로 if 식을 삼항 연산자적으로 사용할 경우, 분기 후의 식이 1개라면 아래와 같이 {}를 생략할 수 있지만,

println(if (x == 0) "ZERO" else "NOT ZERO")

try ~ catch인 경우 {}는 생략할 수 없다.

아래와 같이 작성할 수는 없다.

val num = try s.toInt() catch (e: NumberFormatException) null



최종 수정 : 2023-12-17