[기초] 코틀린에서 null을 다루는 방법

반환타입에서도 null이 들어갈 수가 있다

fun startsWithA1(str: String?): Boolean {
    if(str == null){ throw IllegalArgumentException("null이 들어왔습니다") }

    return str.startWith("A")
}

fun startsWithA2(str: String?): Boolean? {
    if(str == null){ return null }

    return str.startWith("A")
}

fun startsWithA1(str: String?): Boolean {
    if(str == null){ return false }

    return str.startWith("A")
}

 

Safe Call

: null이 아니면 실행하고, null이면 실행하지 않는다(그대로 null)

val str: String? = "ABC"
println(str?.length)

만약 여기서 str의 length를 출력하려고 할 때,

str.length로 작성하게 된다면 null이 들어갈 수 있는 변수에 대해서는 . 을 바로 쓸 수 없다는 오류가 뜬다.

 

따라서 null이 아닌 경우에만 호출해달라고 ?. 를 써야한다.

str이 실제로 var str: String? = null이 되면 출력도 null이 출력된다(전체가 null이기 때문에)

 

Elvis 연산자

: 앞의 연산 결과가 null이면 뒤의 값을 사용

val str: String? = "ABC"
str?.length ?: 0

str?.length가 null이면 0이 출력되고, null이 아니면 값이 그대로 출력될 것이다.

 

Elvis 연산을 이용해서 early return에서 사용할 수 있다.

fun calculate(number: Long?): Long {
	number ?: return 0
    // 다음 로직...
}

 

 

위의 두가지를 이용해서 다시 코드를 짜보면

fun startsWithA1(str: String?): Boolean {
    return str?startWith("A")
    	?: throw IllegalArgumentException("null이 들어왔습니다")
}

fun startsWithA2(str: String?): Boolean? {
    return str?.startWith("A")
}

fun startsWithA1(str: String?): Boolean {
    return str?.startWith("A") ?: false
}

위와 같이 간단하게 줄일 수 있다.

 

null 아님 단언(not-null assertion) 연산자

: nullable type이지만, 절대 null이 될 수 없는 경우(변수가 null이 아님을 컴파일러에게 강제로 알려주는 역할)

fun startsWith(str: String?): Boolean{
	return str!!.startWith("A")
}

 

플랫폼 타입

: 코틀린이 null 관련 정보를 알 수 없는 타입(Runtime 시 Exception이 날 수 있다)

 

보통 Java코드를 코틀린에서 갖다가 쓸 때에 코틀린이 어느정도는 알아서 이해한다.

public class Person {
	private final String namge;
    
    public Person(String name){
    	this.name = name;
    }
    
    @Nullable
    public String getName(){
    	return name;
    }
}

 

예를 들어 Person이라는 객체는 자바로 만들었다고 하자.

코틀린에서는 저 Person을 사용 할 것이다.

fun main(){
    val person = Person("연이")
    startsWithA(person.name)
}

fun startsWithA(str: String): Boolean {
    return str.startsWith("A")
}

@Nullable이라는 어노테이션으로 인해 person.name은 오류가 발생한다.

따라서 @Notnull을 사용하여 null 허용이 되지 않아야 한다.

 

만약 관련 어노테이션이 전혀 없다면?

=> 컴파일에서는 문제가 되지 않지만, 실제로 값이 null로 들어오게 될 경우(Person(null)) 에는 실행 시 에러가 발생한다