티스토리 뷰

반응형

코틀린과 자바의 대표적인 차이점이 몇 가지 있는데 그중 Null Safety에 대해서 기록.

Java와 같은 여러 언어들은 기본적으로 객체에 Null 값을 허용해 줍니다.

그렇기 때문에 Null 객체를 호출해서 사용을 하려고 하고, 이때 null 참조 예외 ( == NullPointerException == NPE )가 발생합니다.

정말,, 많이 본 오류 ^^,,

그래서 코틀린은 객체가 기본적으로 Null을 허용하지 않도록 해서 NPE 오류를 없애려고 합니다.

하지만 기본 값이 Non-Null이지 Nullable로 객체를 선언할 수 있습니다.

 

Non-Null, Nullable 객체 선언

var a: String = "abc" // 기본적으로 a 변수를 선언하고 값을 할당하는 경우 Null이 아님을 의미
a = null // a 변수에 null을 할당하면 컴파일 오류가 발생

null을 허용하려면 아래처럼 ? 를 이용해서 변수를 nullable 문자열로 선언할 수 있습니다.

var b: String? = "abc" // 자료형 뒤에 ?를 사용하면 Nullable 변수
b = null // 정상
print(b)

결국 코틀린에서도 Nullable로 객체를 생성하면 NPE 오류가 발생할 수 있는데 이걸 방지하기 위해 코틀린에서는 여러 방법을 제공합니다.

 

Safe calls ( = 안전한 호출 ) ?.

아래 코드는 String 형의 Nullable 객체이며, null로 b 변수를 초기화시켰습니다.

null이기 때문에 b.length를 출력할 경우 오류가 발생해야 하지만, ?. 연산자를 사용해서 null 값이 출력됩니다.

val b: String? = null
println(b?.length) // null

이 연산자는 chain 형태로 연속적인 변수의 null을 체크할 때 유용합니다.

아래처럼 작성하면 if문을 중복으로 사용해서 조건별로 null을 출력하지 않고 한 줄로만 null을 반환하거나, 값을 출력하거나가 가능합니다. 

bob?.department?.head?.name

위처럼 체인 형태로 작업을 하면 bob, department, head, name과 같은 프로퍼티 중 하나라도 null이라면 null을 return 하게 됩니다.

null이 아닐 경우만 특정 작업을 실행하려면 let 연산자를 함께 사용할 수 있습니다.

val listWithNulls: List<String?> = listOf("Kotlin", null)
for (item in listWithNulls) {
    item?.let { println(it) } // prints Kotlin and ignores null
}

Null을 허용하는 String 리스트를 listWithNulls의 이름으로 선언하고 Kotlin과 null이라는 값으로 초기화해주었습니다.

그 후 for문으로 listWithNulls를 순차 출력 하는데 ?.let을 사용하면 null이 아닌 경우에만 { } 사이의 명령어를 수행하기 때문에 Kotlin 만 출력되고 null은 출력되지 않습니다.

값을 할당할 때도 Safe call을 사용할 수 있습니다.

person?.department?.head = managersPool.getManager()

person이나 department 중 하나라도 null 값이라면 managersPool.getManager() 함수를 호출하지 않습니다.

 

Elvis 연산자 ?:

만약 Nullable 한 변수 b를 사용할 경우 b가 null이 아니면 b값을 사용하고, null이라면 다른 명령을 하고 싶을 때 아래와 같이 코드를 작성할 수 있을 것입니다.

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

?: 를 사용하면 한 줄로 코드를 바꿀 수 있습니다.

val l = b?.length ?: -1

뿐만 아니라 return과 throw 작업도 처리가 가능합니다.

fun foo(node: Node): String? {
    val parent = node.getParent() ?: return null
    val name = node.getName() ?: throw IllegalArgumentException("name expected")
    // ...
}

 

null이 아님을 보증하는 연산자 !!

nullable 한 변수에!! 를 사용하면 개발자가 이 변수는 null이 아니라고 보증하게 됩니다.

NPE 상황이 발생하므로 완전하게 보증할 수 있는 상황이 아니면 사용하지 말고, NPE 예외 처리가 필요할 경우만 사용하는 게 좋습니다.

실제로 개발할 때 사용 해본 적은 없음.

var a: String? = null
val len = a!!.length

 

안전한 캐스팅 as?

다른 자료형으로 변경을 하는 경우 오류가 발생하면 ClassCastException이 발생하는데 이걸 as? 연산자를 이용해서 보완할 수 있습니다.

val a: String = "test"
val b: Int? = a as? Int

a 변수에 test라는 문자열을 넣고 b 변수에 a 변수를 Int 형으로 변환해서 넣는데 String은 Int 형으로 형변환이 불가능하므로 ClassCastException이 발생하는 게 맞지만, b 변수를 ? 를 이용해서 Nullable 하게 선언하고 as? 연산자를 사용하면 b 변수에 null이 할당됩니다.

 

Nullable 유형의 Collection

nullable 유형의 컬렉션이 있고 null이 아닌 요소를 필터링하려는 경우 filterNotNull을 사용해서 null값을 거를 수 있습니다.

val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()

 

이렇게 다양하게 null을 처리할 수 있는 방법을 알아봤습니다.

참고 문서 : https://kotlinlang.org/docs/null-safety.html

반응형

'JAVA, Kotlin' 카테고리의 다른 글

[Kotlin] 예외 처리  (0) 2023.04.09
@Resource, @Autowired, @Inject 차이  (0) 2021.11.01
람다 Lambda 란?  (0) 2021.06.23
컴파일러 vs 인터프리터  (0) 2021.03.04
== 와 equals 차이?  (0) 2021.03.03
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함