본문 바로가기

안드로이드/Kotlin

[Kotlin] 널 안정성(Null safety)

널 안정성(Null Safety)

Java에서 개발하다 가장 많이 겪는 오류는 null pointer exception이다. Kotlin에서는 null값을 허용하기 위해선 자료형 뒤에 ?을 붙여야 한다.

 

엘비스 연산자(?:)

널 값을 허용하지 않는 ?가 없는 값 혹은 변수에 널 값이 반환되는 경우를 대비하여 처리하는 구문이 존재하는 연산자

val postal : PostalCode //null을 허용하지 않음
    = findPostalCode("1600 Pkwy") ?: PostalCode.NONE
    

위의 경우 findPostalCode는 null을 반환할 수도 있는 함수이다. null이 반환되지 않을 경우 적절한 PostalCode 값이 대입되고, null을 반환할 경우 PostalCode.NONE을 대입한다.

 

아래와 같이 값을 반환하는 대신 에외를 발생시킬 수도 있어 유용하다.

fun generateMapWithAddress(address: String) : Image? {
    val postal = findPostalCode(address) ?: throw IllegalStateException()
    
    //지도 이미지 생성
    ...
}

 

안전한 호출(Safe call: ?. 연산자)

객체의 값을 접근하는 경우 객체가 null이 아닐 때만 문장을 수행한다. 아래처럼 변수 대입 시도에 null일 경우 null을 대입하고, 생성되지 않은 foo객체의 bar() 메서드를 수행할 경우 해당 문장은 수행되지 않는다.

// bar가 null이 아닐때만 bar.baz를 대입, bar가 null일 경우 null을 대입
val foo = bar?.baz

//foo가 null이 아닐때만 bar()를 호출
foo?.bar()

 

Non-null assertino(!!)

널 값을 포함할 수 있는 자료형에 널 값이 아님을 보증하는 연산자

val foo: Foo? = ...
val nonNullFoo : Foo = foo!!

non-null assertion을 중첩하여 사용하는 것은 권장되지 않는다.

val contact : Contact = ...
val line : String = contact.address!!.line2!!


class Contact{
    val address: Address?
}

class Address{
    val line2: String?
}

위에서 한 부분이라도 에러가 발생할 경우 에러가 발생한 라인만 확인할 수 있고 address가 null이어서 발생한 에러인지, line2가 null이어서 발생한 에러인지 확인할 수 없다.

 

 

lateinit

코틀린의 경우 대부분 값을 선언과 동시에 초기화 해야 하지만, lateinit을 사용할 경우 변수만 선언 가능하다. 다만, 사용시 널 포인터 에외가 발생할 수 있으니 이를 잘 고려해야 한다.

 

class Activity: Activity(){
    lateinit var api : Api
    ...
}