코틀린의 예외처리는 자바나 다른 언어의 예외 처리와 비슷하다.
함수는 정상적으로 종료할 수 있지만 오류가 발생하면 예외를 던질 수 있다. (throw)
발생한 예외를 함수 호출 단에서 처리(catch)하지 않으면 함수 호출 스택을 거슬러 올라가면서 예외를 처리하는 부분이 나올 때까지 예외를 다시 던진다.(rethrow)
if (percentage !in 0..100) {
throw IllegalArgumentException(
"A Percentage value must be between 0 and 100: $percentage")
}
다른 클래스와 마찬가지로 예외 인스턴스를 만들 때도 new를 붙일 필요가 없다. (예를 들어, 자바에서 new Person() 이라고 객체를 만들어줘야 하는 것이 아니라 코틀린에서는 Person() 이라고만 선언해줘도 클래스 객체가 선언되는 것처럼)
자바와 달리 코틀린의 throw는 식이므로 다른 식에 포함될 수 있다.
val percentage =
if (number in 0..100)
number
else
throw IllegalArgumentException( // throw는 식이다.
"A percentage value must be between 0 and 100: $number")
자바와 마찬가지로 예외를 처리하려면 try와 catch, finally 절을 함께 사용한다.
fun readNumber(reader: BufferedReader) : Int? { // 함수가 던질 수 있는 예외를 명시할 필요가 없다.
try{
val line = reader.readLine()
return Integer.parseInt(line)
}
catch (e: NumberFormatException) { // 예외 타입을 :의 오른쪽에 쓴다 (자바와 문법적 차이)
return null
}
finally { // finally는 자바와 똑같이 작동한다. (오류가 발생하든 안 발생하든 실행하라는 뜻)
reader.close()
}
}
-> val reader = BufferedReader(StringReader("239"))
-> println(readNumber(reader))
239
자바코드와 가장 큰 차이는 throws 절이 코드에 없다는 점이다.
무슨 말인가 하면 대충 자바는 체크 예외를 명시적으로 처리해줘야 한다는 뜻이다.
코틀린은 안 해줘도 된다.
try를 식으로 사용하여 위의 예제를 finally절을 없애고 파일에서 읽은 수를 출력하는 코드를 추가해보자
fun readNumber(reader: BufferedReader) {
val number = try {
Integer.parseInt(reader.readLine()) // 이 식의 값이 try 식의 값이 된다.
} catch (e: NumberFormatException) {
return
}
println(number)
}
-> val reader = BufferedReader(StringReader("not a number"))
-> readNumber(reader) // 아무것도 출력되지 않는다.
위 예제는 catch 블록 안에서 return문을 사용했지만 아무 값을 리턴해주지 않았기 때문에 아무것도 출력되지 않는다.
만약
} catch (e: NumberFormatException) {
null
}
로 값을 준다면
예외가 발생했을 때 null 값을 사용한다.