본문 바로가기
Kotlin

[Kotlin] 기초 문법 정리 - 변수와 널(null)

by Saerong2 2020. 9. 8.

 

안녕하세요 VisionARy입니다.

이번 글에서는 코틀린의 변수에 대해서, 그리고 null값을 어떻게 다루는지 알아보겠습니다.

 

 

# 변수선언

코틀린의 변수 선언에는 지난시간에 배운 것처럼 초기화 값으로 타입추론이 가능하기에 자료형의 생략이 가능합니다.

따라서 자료형을 생략하고 값의 수정여부에 따라 val 키워드나 var 키워드를 사용하여 선언할 수 있습니다.

  • val (value) : val 키워드는 변수가 한 번 초기화 되면 수정이 불가능합니다
  • var (variable) : var 키워드는 그 이외에 값의 수정이 가능할 때 사용합니다

즉, val은 변수가 불변(immutable)일 때, var은 변수가 가변(mutable)일 때 사용하면 됩니다.

val에 대해서는 아래에서 조금 더 자세히 다룹니다.

 

코틀린에서 타입추론은 당연하게도 초기화 된 값을 기반으로 이루어지기 때문에 변수 선언시 초기화를 해주지 않는다면 컴파일 타임에 에러가 발생합니다. 따라서 값의 초기화를 변수선언과 분리해서 나중에 한다면 타입을 지정해 주어야 합니다.

하지만, 클래스에서의 멤버 변수(property)의 선언시에는 반드시 멤버 변수에 대한 초기화가 필요하기 때문에 값을 지정해 주어야 하는데요, lateinit 키워드를 사용하여 초기화를 미룰 수 있지만 이에 대해서는 다음에 클래스에서 다루도록 하고 기본적으로 변수선언에는 mutability에 따라 val과 var 키워드만 적절히 사용하면 된다고 알아가면 되겠습니다.

 

# Internal Mutability, Content Mutability

위의 설명을 보면 "아~ val은 immutable한 변수를 선언할 때 사용하는 거구나!" 라고 생각할 수 있습니다.

하지만 보다 정확하게 val은 reference를 바꿀 수 없는 것입니다. 

위의 예제에서 immutableList는 list이므로 immutable합니다.따라서 100으로 값을 변경하는 것은 허용되지 않죠.

val 때문에 값을 변경할 수 없는 것이 아닙니다. var로 해도 똑같은 에러가 나오게 됩니다.

 

위의 예제에서는 val 변수가 가리키는 list가 mutable이므로 mutableList는 그 content를 바꿀 수 있습니다.

 

map은 val이기 때문에 map2가 참조하는 레퍼런스로 변경하는 것이 불가능 합니다.

# 널(null)

코틀린은 변수를 사용할 때 반드시 값이 할당되어 있어야 하는 원칙이 있습니다. 변수의 값이 할당되어 있지 않은 상태를 null이라고 합니다. 코틀린에서는 기본적으로 null을 허용하지 않기 때문에 오류가 발생합니다. 코틀린에 대한 소개글에서 밝혔듯, 코틀린은 NullPointerException를 컴파일 타임에 알 수 있습니다.

수학에서 0이라는 값이 필요하듯이 프로그래밍에서도 null을 유용하게 사용할 때가 있습니다. 그렇기 때문에 코틀린에서 기본적으로는 null을 허용하지 않지만 물음표(?) 기호를 사용하면 null 값을 갖는 변수를 허용할 수 있습니다. 대신, null을 검사하고 처리하는 방법을 제공함으로써 안전하게 null을 처리할 수 있습니다.

null에 대한 코틀린의 공식 문서는 여기에서 확인 할 수 있습니다.

 

코틀린에서 null과 관련된 주 키워드는 다음과 같은 것이 있습니다.

  ? (nullable) ?. (safe call) ?: (Elvis operator) !! (not-null assertion)
설명 변수가 null 값을 가질 수 있습니다 멤버 선택 연산자(.)를 실행하기 전에 변수가 null값을 갖는지 확인하고 처리합니다 b가 null이 아니라면 그 값을 사용하고 null이라면 지정한 non-null 값을 사용합니다 변수를 non-null 타입으로 변환하고 실행합니다.
만약 null이라면 throw exception을 합니다.
예제 var str : String?
= null
fun getSize(str: String?): Int? { return str?.length } val len = b?.length ?: -1 val len = b!!.length

 

  • ? (nullable)

코틀린은 기본적으로 null을 허용하지 않습니다. 하지만 자료형 뒤에 ?(nullable)을 붙여주면 null 값을 사용할 수 있습니다. null값을 허용해 줌으로 인해 생기는 문제들이 있는데요. 코틀린에서는 어떻게 이 문제를 해결하는지 알아봅시다.

 

  • ?. (safe call)

예를 들어서 문자열의 길이를 알고 싶을 때, 우리는 String 클래스의 length() 메서드를 사용할 수 있습니다.

하지만 String 변수가 nullabe이라면 어떨까요? 코틀린에서는 다음과 같이 safe call을 통해 null을 회피합니다.

nullStr은 null값을 갖고 있기 때문에 String의 length() 메서드가 실행되지 않고 null을 반환하게 됩니다.

 

이를 활용하면 null인지 체크하는 if문 하나 없이도 safe call은 이런식으로 연속적으로도 사용할 수 있습니다!

 

  • ?: (Elvis operator)

 

 

Elvis opertor 이름의 유래는 가수 Elvis Presley를 닮아서 붙여졌다고 합니다! 닮은 것 같나요? ㅎㅎㅎ

Elvis operator는 safe call과 함께 사용하여 C언어에서 삼항연산자와 비슷한 역할을 합니다.

 

이해를 돕기 위해 아래와 같은 예를 들어 설명하겠습니다. b?.length를 먼저보면 b가 null인 경우 null을, b가 null이 아닌 경우 b.length를 반환합니다. 이어서 ?:는 앞의 결과가 null이 아니라면 그 값을 그대로 반환하고 null이라면 ?:의 오른쪽 식인 -1을 반환합니다.

결과적으로, b가 null이라면 easyWay = -1이 되고, b가 null이 아니라면 easyWay = b.length가 됩니다.

 

  • !! (not-null assertion operator)

!! 는 NPE-lover를 위한 키워드입니다.

변수를 강제로 non-null 타입으로 변환하고 실행합니다. 하지만 만약 null이라면 NPE를 throw합니다.

따라서 일부로 NPE를 발생시켜야 하는 경우에 활용할 수도 있습니다.

 

# 마치며

이번 시간에는 코틀린의 변수선언과 null에 대한 시스템을 배웠습니다.

null 참조에 대한 개발자의 부담을 확실히 덜어주는 편의성이 느껴지지 않나요?

다음 시간에는 코틀린의 함수에 대해서 다루겠습니다.

감사합니다.

댓글