티스토리 뷰
목차
배경
코틀린은 개발자의 편의를 위해 자주 쓰이는 로직(단순 조건 체크과 예외 throw 등)을 매번 구현할 필요없이 손쉽게 사용할 수 있는 간편한 많은 기능을 제공한다. 이번에는 그 중 구문에 대한 체크와 예외 처리를 간편하게 할 수 있는 check(), require(), checkNotNull(), requireNotNull()를 살펴본다.
check()
안에 있는 구문이 false라면 IllegalStateException를 던진다.
해당 메서드의 구현을 살펴보면 다음과 같다. Boolean 타입의 체크할 조건을 value를 매개변수로 받고 조건을 만족하지 않으면 전달받은 함수 lazyMessage를 실행하여 예외 메시지(message)를 생성한다. 생성한 예외 메시지를 통해 IllegalStateException을 던진다.
@kotlin.internal.InlineOnly
public inline fun check(value: Boolean, lazyMessage: () -> Any): Unit {
contract {
returns() implies value
}
if (!value) {
val message = lazyMessage()
throw IllegalStateException(message.toString())
}
}
예외 메시지인 lazyMessage가 () -> Any 타입의 함수로 정의되어 있고, 조건을 만족하지 않는 경우에만 이 함수를 호출하여 메시지를 생성한다. 이를 통해 메시지 생성 비용을 효율적으로 관리하고 불필요한 계산을 방지한다.
사용 방식은 다음과 같다. 체크할 조건과 조건을 만족하지 못할 경우 예외 메시지를 생성하기 위한 () -> Any 타입 함수를 전달한다.
fun errorMessage(): Any {
return "공개된 리뷰가 아닙니다."
}
// 메서드 참조로 함수 자체를 전달한다.
check(review.isPublic(), ::errorMessage)
이는 다음과 같이 익명함수로도 호출할 수 있다.
check(review.isPublic(), fun(): Any {
return "공개된 리뷰가 아닙니다."
})
가장 추천하는 방안은, 다음과 같이 코틀린의 람다식 { }으로 호출하는 것이다.
check(review.isPublic()) { "공개된 리뷰가 아닙니다." }
체크할 조건과 조건을 만족하지 않을 경우 던질 메시지를 람다 표현식으로 전달함으로써, 간결하고 명확하게 조건(review.isPublic()을 체크(check)하고 아니라면, 예외를 던진다는 의도를 표현할 수 있다.
require()
조건 구문이 false라면 IllegalArgumentException를 던진다. 구현을 살펴보면 다음과 같다.
@kotlin.internal.InlineOnly
public inline fun require(value: Boolean, lazyMessage: () -> Any): Unit {
contract {
returns() implies value
}
if (!value) {
val message = lazyMessage()
throw IllegalArgumentException(message.toString())
}
}
사용 예시는 다음과 같다. 위와 마찬가지로 람다 표현식으로 간략하고 명시적으로 호출할 수 있다.
require(!tokens.isNullOrBlank()) { "입력값이 비어있습니다." }
checkNotNull()
check()와 반대로 조건을 만족하지 않으면 IllegalStateException을 던진다. 구현을 살펴보면 다음과 같다.
@kotlin.internal.InlineOnly
public inline fun <T : Any> checkNotNull(value: T?, lazyMessage: () -> Any): T {
contract {
returns() implies (value != null)
}
if (value == null) {
val message = lazyMessage()
throw IllegalStateException(message.toString())
} else {
return value
}
}
requireNotNull()
require()와 반대로 조건을 만족하지 않으면 IllegalArgumentException 예외를 던진다. 구현을 살펴보면 다음과 같다.
@kotlin.internal.InlineOnly
public inline fun <T : Any> requireNotNull(value: T?, lazyMessage: () -> Any): T {
contract {
returns() implies (value != null)
}
if (value == null) {
val message = lazyMessage()
throw IllegalArgumentException(message.toString())
} else {
return value
}
}
예시 - 스마트 캐스트(Smart Cast) 활용
앞서 살펴본 check(), require(), checkNotNull(), requireNotNull()은 스마트 캐스트를 활용할때 특히 유용하다. 이를 활용하여 null 여부를 제거하고 타입을 보장하면, 코틀린 컴파일러는 이후 코드를 안전하게 실행할 수 있도록 자동으로 변환해준다. 따라서 코드를 간결하고 안정적으로 유지할 수 있다.
fun calculate(tokens: String?): Double {
requireNotNull(tokens) { "입력값이 비어있습니다." }
// 이후 로직 실행 - 스마트 캐스트로 tokens를 바로 String 타입으로 사용할 수 있다.
val tokenList = tokens.split(" ")
...
}
'Java & Kotlin' 카테고리의 다른 글
[Kotlin] 코틀린의 인라인 클래스 (Inline value classes) (2) | 2024.12.09 |
---|---|
[JVM] JVM 기반언어, 자바와 코틀린의 빌드 과정과 실행 원리 (1) | 2024.11.24 |
[Java] 자바의 두가지 정렬 방법(Comparable, Comparator) (0) | 2024.08.01 |
[Java] 주요 함수형 인터페이스(Function Interface) (2/2) (0) | 2024.03.19 |
[Java] 함수형 프로그래밍(Functional Programming)과 람다식(Lambda Expression) (1/2) (0) | 2024.03.10 |