Uknow's Lab.
article thumbnail

 

오류(Error)

오류는 프로그래밍을 하다 보면 정말 수도 없이 마주칩니다.

예기치 못한 동작을 하거나, 의도하지 않게 동작하거나, 심지어 프로그램이 아에 종료될 수도 있습니다.

대표적인 오류 상황이 뭐가 있을까요?

 

 

길이가 3인 배열의 10번째 원소를 접근한다면?

fun main() {
    val arr = arrayOf(1, 2, 3)
    arr[10] = 12345
}

// 에러 메시지
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3
	at PracticeKt.main(Practice.kt:7)
	at PracticeKt.main(Practice.kt)

 

길이가 3인 배열이지만, 10번째 원소를 접근하게 된다면 당연하게도 에러가 발생되며 프로그램이 종료됩니다.

 

 

숫자를 0으로 나누면?

fun main() {
    val a = 3 / 0
}

// 에러 메시지
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at PracticeKt.main(Practice.kt:6)
	at PracticeKt.main(Practice.kt)

 

숫자를 0으로 나눌 수 있을까요? 이는 수학적으로 불가능합니다.

그럼, 프로그램에서 0으로 나눈다면 어떻게 될까요?

당연하게도, 못나눕니다. 프로그램이 에러를 일으키며 강제 종료됩니다.

 

0으로 나누는 경우는 그리 경험해본 적이 많이는 없지만,

배열 인덱스와 nullPointerExceptino 같은 경우는 정말 정말 정말 많이 보게됩니다…ㅎㅎ

그래서 코틀린 같은 경우는 개발자의 실수를 줄여주기 위해 언어 차원에서 null 처리에 관한 기능이 많은 것이고요.

 

 

예외를 잡아 처리한다 : try - catch

fun main() {
    println("program start")
    try {
        val a = 3 / 0
    } catch (e: ArithmeticException) {
        println("오류")
    }
    println("program end")
}


// 출력
program start
중간에 오류남
program end

 

저는, 이러한 오류가 발생되더라도 프로그램이 종료되지 않고 계속 수행되게 하고 싶습니다.

 

그럴 땐 try - catch를 사용하면 됩니다.

try 블럭 안에서 에러가 발생되더라도 프로그램이 종료되지 않으며,

에러가 발생되면 catch 안의 블럭이 수행됩니다.

 

물론, 에러가 발생되지 않으면 catch 안의 블럭은 수행되지 않습니다.

 

 

catch에서 에러 메시지 출력하기

fun main() {
    println("program start")
    try {
        val a = 3 / 0
    } catch (e: ArithmeticException) {
        println("에러 메시지 : ${e.message}")
    }
    println("program end")
}


// 출력
program start
에러 메시지 : / by zero
program end

 

 

에러가 발생되던, 발생되지 않던, 이 블록은 수행되어야 해! : finally

// case 1 - 예외 발생 (배열 인덱스)

fun main() {
    println("program start")

    try {
        val array = arrayOf(1, 2, 3, 4, 5)
        array[10] = 10
    } catch (e: Exception) {
        println("예외 발생!")
    } finally {
        println("try - catch 부분이 끝났습니다.")
    }

    println("program end")
}


// 출력
program start
예외 발생!
try - catch 부분이 끝났습니다.
program end



======================================================================

// case 2 - 정상 작동
fun main() {
    println("program start")

    try {
        val array = arrayOf(1, 2, 3, 4, 5)
        array[1] = 10
    } catch (e: Exception) {
        println("예외 발생!")
    } finally {
        println("try - catch 부분이 끝났습니다.")
    }

    println("program end")
}

// 출력
program start
try - catch 부분이 끝났습니다.
program end

 

finally 블럭안의 부분은 예외의 발생여부에 관계없이 항상 수행되는 블럭입니다.

위 코드는 길이가 5인 배열에 10번째 원소를 접근해 예외가 발생되는 코드,

아래는 정상적으로 작동되는 코드입니다.

 

두 경우 모두 finally 블럭이 작동하는 것을 볼 수 있습니다.

 

 

try - catch 표현식

fun main() {
    val n = try {
        val arr = arrayOf(1, 2, 3, 4, 5)
        arr[10]
    } catch (e: Exception) {
        -1
    }

    println(n)
}

// 출력
-1

 

if, when과 같이 try - catch 역시 표현식으로 나타낼 수 있습니다.

n에서 arr의 10번째 원소를 대입하고, 에러가 발생할 경우 -1을 n에 대입하는 코드입니다.

 

당연하게도, 에러가 발생되었기에 -1이 n에 대입된 모습입니다.

 

 

강제로 에러 일으키기 (에러 던지기) : throw

fun main() {
    val a = 1234
    if (a !in 1..1000) {
        throw IllegalArgumentException("a는 1이상 1000이하의 정수여야 합니다.")
    }
}

 

 

throw는 예외를 던지는 키워드입니다.

혹은, 예외를 강제로 발생시키는 키워드라 생각할 수도 있겠습니다.

에러를 던진다… 뭔가 말이 잘 와닿지 않죠? 에러를 강제로 일으킨다. 라고 생각하는게 편할 것 같습니다.

 

파이썬에서 동일한 기능을 하는, 에러를 강제로 일으키는 키워드는 raise 입니다. 뭔가 더 와닿네요.

profile

Uknow's Lab.

@유노 Uknow

인생은 Byte와 Double 사이 Char다. 아무말이나 해봤습니다.