티스토리 뷰

Computer/Android

[Kotlin] 코틀린 Nullable

jamezc 2020. 9. 16. 02:01

 

 

아래와 같은 에러 문구가 발생 하는 이유와 해결 방법

Smart cast to 'abc' is impossible, because 'abc' is a mutable property that could have been changed by this time

사용한 변수가 Nullable 인경우 ? 을 입력하여 Nullable 상태를 확인한다.

 backToast = Toast.makeText(this, resources.getString(R.string.hello), Toast.LENGTH_SHORT)
 backToast.show() // Error Happen
 backToast = Toast.makeText(this, resources.getString(R.string.hello), Toast.LENGTH_SHORT)
 backToast?.show() // Fixed

 

 

Nullable과 Non-Nullable 프로퍼티

코틀린에서는 Nullable과 Non Nullable 타입이 존재합니다. 타입을 선언할 때 ?를 붙이면 null을 할당할 수 있는 프로퍼티이고, ?가 붙지 않으면 null이 허용되지 않는 프로퍼티를 의미합니다.

var nullable: String? = "nullable"
var nonNullable: String = "non-Nullable"

각 변수에 Null 값이 있는 경우 컴파일 결과

nullable = null      // 컴파일 성공
nonNullable = null   // 컴파일 에러

 

nullable 타입을 non-nullable 타입으로 변경하기

코틀린에서 아래와 같은 자바 라이브러리를 사용한다고 가정하겠습니다. 이 함수는 String을 리턴하며, 코틀린에서는 이 타입을 nullable인 String?으로 인식합니다.

String getString() {
  String str = "";
  ..
  return str;
}

코틀린에서 이 함수의 리턴 값을 non-nullable인 String으로 변환하고 싶습니다. 그럼 이 프로퍼티가 항상 null이 아닌 것을 보장할 수 있고, try-catch 로 NPE를 처리하지 않아도 됩니다. 하지만 아래 코드처럼 대입하면 컴파일 에러가 발생합니다. String?타입을 String타입에 할당하려고 했기 때문입니다.

var str1: String = getString()     // 컴파일 에러

반면에 아래 코드는 컴파일됩니다. 그 이유는 !! 연산자를 사용했기 때문입니다. !!연산자는 객체가 null이 아닌 것을 보장합니다. 만약 null이라면 NPE를 발생시킵니다.

var str2: String = getString()!!   // 컴파일 성공

이런 이유로 !!연산자는 null이 아닌 것을 보장할 수 있는 객체에만 사용해야 합니다.

 

안전하게 nullable 프로퍼티 접근하기

코틀린에서 nullable 프로퍼티를 안전하게 접근하는데 사용하는 다양한 방법들에 대해서 알아보겠습니다.

조건문으로 nullable 접근

가장 쉬운 방법은 if-else를 이용하는 것입니다. 자바에서는 흔히 사용하는 방식입니다.

아래 코드는 String?을 접근하기 전에 if로 null을 체크하는 코드입니다.

val b: String? = "Kotlin"
if (b != null && b.length > 0) {
    print("String of length ${b.length}")
} else {
    print("Empty string")
}

 

Safe call 연산자로 nullable 접근

Safe call은 객체를 접근할 때 ?.로 접근하는 방법을 말합니다. 예를들어 아래 코드에서 b?.length를 수행할 때 b가 null이라면 length를 호출하지 않고 null을 리턴합니다. 그렇기 때문에 NPE가 발생하지 않습니다.

val a: String = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) // Unnecessary safe call

위의 코드에서 a?.length는 불필요하게 Safe call을 사용하고 있습니다. a는 Non-nullable이기 때문입니다.

아래 여러 객체로 둘러 쌓인 String에 접근하는 코드입니다. a?.b?.c?.d?를 수행할 때, 이 객체들 중에 null이 있으면 null을 리턴합니다.

println(a?.b?.c?.d?.length)

 

안전하게 nullable 프로퍼티 할당

어떤 프로퍼티를 다른 프로퍼티에 할당할 때, 객체가 null인 경우 default 값을 할당하고 싶을 수 있습니다.

if-else

if-else로 삼항연산자를 대체할 수 있습니다. 자바와는 다르게 코틀린은 한줄로 if-else를 쓸 수 있습니다. 다음은 if-else를 사용하여 삼항연산자와 동일한 내용을 구현한 코드입니다.

val l = if (b != null) b.length else -1

엘비스 연산자(Elvis Operation)

엘비스 연산자는 ?:를 말합니다. 삼항연산자와 비슷한데 ?: 왼쪽의 객체가 null이 아니면 이 객체를 리턴하고 null이라면 ?:의 오른쪽 객체를 리턴합니다. 다음은 위의 if-else 예제를 엘비스 연산자를 사용하여 구현한 코드입니다.

val l = b?.length ?: -1

 

 

 

'Computer > Android' 카테고리의 다른 글

[Kotlin] Visibility  (0) 2020.10.03
[Kotlin] 산술연산자, 비트연산자  (0) 2020.09.25
[Kotlin] 코틀린 이란?  (0) 2020.09.16
[Android] Touch, Gesture, Key Event 처리  (0) 2020.05.05
[Android] EditText 스크린 키보드 설정  (0) 2020.03.13
댓글

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음



Total
Today
Yesterday
최근에 달린 댓글