오늘도 넷플릭스로 플래쉬(Flash)를 시청하면서
코틀린(Kotlin) 학습을 이어가겠습니다
주제는 제목처럼 코틀린의 null과 예외(Exception)처리입니다
null은 var이나 val 변수의 값이 없다는 것을 나타내는 값인데
자바를 포함해서 많은 프로그래밍 언어에서
null은 프로그램이 중단되는 크래시(crash)를 유발하는 원인이 됩니다
이유는 컴파일 시점에 에러를 알 수 없기 떄문인데
코틀린은 null 가능 타입과 불가능 타입을 구분하여
위험을 사전에 방지할 수 있습니다
fun main(args: Array<String>) {
var beverage = readLine()?.capitalize()
println(beverage)
}
위의 코드에서 readLine() 다음에 ?를 붙이지 않는다면 에러가 발생합니다
이유는 readLine() 함수의 반환 타입이 String? 로
null이 가능하기 때문인데 이를 컴파일이나 런타임 에러 없이
항상 실행되도록 해야하는 경우에는
안전 호출 연산자(safe call operator)인 ?를 붙입니다
이렇게 하면 readLine()의 반환값이 null이 아닌 경우에만
capitalize()가 안전하게 호출됩니다
fun main(args: Array<String>) {
var beverage = readLine()?.let{
if (it.isNotBlank()) {
it.capitalize()
} else {
"맥주"
}
}
println(beverage)
}
위의 코드는 let과 ?를 이용하여
안전하게 null을 처리하는 방법입니다
fun main(args: Array<String>) {
var beverage = readLine()!!.capitalize()
println(beverage)
}
반면에 non-null 단언 연산자(assertion operator)인 !!도 있는데
위의 코드처럼 사용하면 readLine()의 결과가 null이어도
capitalize()를 실행하므로 런타임에 Exception이 발생할 수 있습니다
(콘솔 입력 시에 Ctrl + D를 누르면 null이 발생됩니다)
fun main(args: Array<String>) {
var beverage = readLine()
if (beverage != null) {
beverage = beverage.capitalize()
} else {
println("beverage is null")
}
val beverageServed: String = beverage ?: "beer"
println(beverageServed)
}
위의 코드는 if 문으로 null 여부를 체크하고
beverageServed 변수에 beverage가 null이면 "beer"를
null이 아니면 beverage 값을 넣습니다
이 때 ?: 는 null 복합 연산자(null coalescing operator)라고 하고
이를 이용해서 위의 코드를 아래와 같이 줄일 수 있습니다
fun main(args: Array<String>) {
var beverage = readLine()
beverage?.let {
beverage = it.capitalize()
} ?: println("beverage is null")
val beverageServed: String = beverage ?: "beer"
println(beverageServed)
}
다음으로 예외(Exception) 처리에 대해 알아보겠습니다
import java.lang.Exception
import java.lang.IllegalStateException
fun proficiencyCheck(swordsJuggling: Int?) {
//swordsJuggling ?: throw UnskilledSwordJugglerException()
/* precondition function */
checkNotNull(swordsJuggling, { "Player cannot juggle" })
}
class UnskilledSwordJugglerException() : IllegalStateException("Player cannot juggle")
fun main(args: Array<String>) {
var swordsJuggling: Int? = null
var isJugglingProficient = (1..3).shuffled().last() == 3
if (isJugglingProficient) {
swordsJuggling = 2
}
try {
proficiencyCheck(swordsJuggling)
swordsJuggling = swordsJuggling!!.plus(1)
} catch (e: Exception) {
println(e)
}
if (swordsJuggling != null) {
if (swordsJuggling == 1) {
println("Juggle with $swordsJuggling knife")
} else {
println("Juggle with $swordsJuggling knives")
}
} else {
println("No knife")
}
}
위의 코드를 보면 try문 안에서 proficiencyCheck() 함수를 호출합니다
이 함수는 파라미터로 받은 값의 null 여부를 확인해서
null일 경우 커스텀(custom) 예외로 IllegalStateException를 상속한
UnskilledSwordJugglerException에 예외를 던지고
이 클래스에서 IllegalStateException을 발생시킵니다
본래는 크래쉬(crash)가 발생해야하지만
try 문을 통해 예외처리를 하였으므로
catch문 안에 println()에 의해 "Player cannot juggle"이 출력되고
아래의 No knife를 출력하고 종료됩니다
또 proficiencyCheck() 함수를 보시면 checkNotNull() 함수가 있는데요
(주석 처리부분과 동일한 결과)
이는 전제 조건 함수(precondition fuction)이라고해서
코틀린이 제공하는 표준 라이브러리 함수합니다
함수 | 설명 |
checkNotNull | 첫번째 인자값이 null이면 IllegalStateException을 발생시키며, 그렇지 않으면 첫번째 인자값을 반환 |
require | 첫번째 인자값이 false면 IllegalArgumentException을 발생시킴 |
requireNotNull | 첫번째 인자값이 null이면 IllegalArgumentException을 발생시키며, 그렇지 않으면 첫번째 인자값을 반환 |
error | 첫번째 인자값이 null이면 제공된 메시지와 함께 IllegalStateException을 발생시키며, 그렇지 않으면 첫번째 인자값을 반환 |
assert | 인자값이 false면 AssertionError를 발생시키고 컴파일러의 assertion flag가 활성화됨 |
코틀린에서는 모든 예외가 unchecked 예외로
예외가 생길 수 있는 모든 코드를 try/catch 문으로
반드시 처리하도록 컴파일러가 강요하지 않습니다
참고로 checked 예외는 처리하지 않을 경우 컴파일 오류가 발생합니다
이것으로 이번 학습을 마치겠습니다
그럼 이만-_-
'Android' 카테고리의 다른 글
[Android] 코틀린(Kotlin) 표준 라이브러리 함수(Standard Library Functions) (0) | 2020.04.26 |
---|---|
[Android] 코틀린(Kotlin) 문자열(String)과 숫자(Numeric) (0) | 2020.04.21 |
[Android] 코틀린(Kotlin) 함수(Function) (0) | 2020.04.18 |
[Android] 코틀린(Kotlin) 변수(Variable)/상수(Constant)/데이터 타입(Data type)/제어 흐름(Control flow) (0) | 2020.04.17 |
[Android] 인텔리제이(IntelliJ IDEA) 설치 (0) | 2020.04.16 |