[Kotlin] null

choieunin·2022년 7월 1일
0

Kotlin

목록 보기
2/2

1. null

코틀린의 변수 선언은 기본적으로 null을 허용하지 않는다.

  • 변수 선언
val a: Int = 30
val b: String = "Hello"

위와 같이 올바른 변수 선언문에서 30"Hello"를 버린다면 오류이다.

  • null 가능한 선언
val a: Int? = null
val b: Stirng? = null

이처럼 자료형 뒤에 물음표 기호(?)를 명시해야 한다.

Int vs Int?
String vs String?
Long vs Long?
.
.

뿐만 아니라 다른 자료형 모두 두 가지의 선언 방법이 있다.


null 가능한 선언들은 null일 가능성이 있기 때문에 가능성 검사를 해주어야 한다.
체크해주지 않는다면 사용할 수 없는 null인 변수에 접근하면서 발생하는 예외가 생긴다. (단순 출력은 상관없으나 널인 상태에서 연산되는 멤버에 접근할 때만)

NPE (NullPointerException)


예제를 보면서 더 자세히 알아보자.

fun main() {
	var str1: String
    println(str1)
}

위 코드를 실행하면 어떻게 될까? 잘못된 곳을 찾아낼 수 있나?

코드를 실행하게 되면

Kotlin: Variable 'str1' must be initialized

라는 오류가 뜰 것이다. 초기화를 해주지 않은 것이다.

fun main() {
	var str1: String
    str1 = "Hi"
    println(str1)
}

이렇게 str1을 초기화 해주어야 한다.

fun main() {
	var str1: String
    str1 = null
    println(str1)
}

이 코드도 당연히 안된다. null을 사용하려면 물음표 기호를 붙어야 하기 때문이다. (kotlin은 기본적으로 null을 선언하지 않는다)

fun main() {
	var str1: String?
    str1 = null
    println(str1)
}

2. 세이프콜(?.)과 non-null

세이프 콜이란 null이 할당되어 있을 가능성이 있는 변수를 검사하여 호출하도록 도와주는 연산자, 사용할 변수 이름 뒤에 ?.을 작성한다.

str1의 길이를 알아보기 위해 아래와 같이 length를 넣어보자.

fun main() {
	var str1: String?
    str1 = null
    println("str1: $str1, length: ${str1.length}")
}

그럼 length 앞 점(.)에 빨간줄이 그어진다.
(String? 형식에는 세이프콜이나 넌널 단정 기호가 허용됩니다 라는 문구를 볼 수 있다)
그 이유는 str1null일 수 있는 가능성이 존재하기 때문에 길이를 알 수 없다.

이 때 필요한게 위에서 언급한 세이프 콜과 non-null이다.

세이프 콜은 아래와 같이 ?.을 넣어준다. (없이 실행하면 NPE 발생)

fun main() {
	var str1: String?
    str1 = null
    println("str1: $str1, length: ${str1?.length}")
}

str1을 실행할건데 혹시라도 null이라면 뒷 부분을 실행하지 않는다는 의미이다.

여기서 하나 더 ! non-null
println("str1: $str1, length: ${str1!!.length}")
이렇게 !!.는 무조건 null일리 없다라고 가정을 해서 오류를 무시한다.
null이더라도 체크하지 않는다.


length를 미리 판단문을 통해 확인할 수 있다. (kotlin은 if문을 한 줄에 작성 가능하다.)

fun main() {
	var str1: String?
    str1 = null
    val len = if (str1 != null) str1.length else -1
    println("str1: $str1, length: $len")
}
str1: null, length: -1

3. 정리하자면

kotlin에서는 기본적으로 NotNull이고 Nullable 표현에만 '?'가 사용된다.

fun set(a: String, b: String?) {
// Do noting
}

var temp: String? = null
var size = -1
if (temp != null) {
	size = temp.length
}

// 또는

var temp: String? = null
val size = if (temp != null) temp.length else -1

세이프 콜과 non-null 단정 기호 활용

fun main() {
	var str1 : Stirng? = "Hello"
    str1 = null
    println("str1: $str1 length: ${str1.length}") 
    //null 허용하면 length가 실행될 수 없음
}
  • 세이프 콜
    str1?.length

  • non-null 단정 기호 (최대한 이건 사용하지 않는 것이 좋다. NPE 발생 가능)
    str1!!.length

profile
안녕하세요! 만나서 반갑습니다!

0개의 댓글