Programing Language/Kotlin

Kotlin Null 처리 방식 정리

칼쵸쵸 2022. 11. 26. 00:26

1. 기본적인 Null 변수 

fun main()
{
    val a:Int;
    // a = null; -> null 할당 불가

    val b:Int?;
    b = null;
}

코틀린에서는 변수 할당 시에 일반적인 변수 선언으로는 null을 할당할 수 없다.

"Type?" 형태로 뒤에 '?'를 추가해야지만 null을 할당 받을 수 있는 변수가 된다.

null이 가능한 타입은 기존의 코틀린 기본 타입과 다른 타입으로 구분된다.

 

2. 함수에서의 null

fun main()
{
    val a = null;
    //add(a); <- 동작 불가
    add_null(a)
}

fun add(a:Int):Int
{
    val b:Int = a+1;
    return b;
}

fun add_null(a:Int?):Int?
{
    if(a==null) return null; //반드시 null체크를 수행해야만 아래 코드가 작성 가능하다.
    val b:Int = a+1; // 만약 위의 내용이 없다면 컴파일 에러 발생
    return b;
}

마찬가지로 파라미터에도 일반적인 형식의 파라미터에는 null값을 입력 할 수 없다.

마찬가지로 return 값에도 '?' 를 추가하지 않는 다면 null을 리턴할 수 없다.

또한 파라미터를 null이 가능한 형식으로 선언한다면 반드시 변수 null 체크에 해당하는 내용을 작성 후에 변수에 관한 내용을 사용할 수 있다. 

 

3. Safe Call

fun main() {
    val a:String? = "hi";
    //val size_a1:Int = a.length <- 불가
    //val size_a2:Int? = a.length <- 불가
    val size_a3:Int? = a?.length;
}

변수에 대한 메서드를 실행할 시에 변수가 null이 가능한 상태라면 해당 메서드를 실행할 수 없다.

해당 변수가 null일 수 있는 경우 변수명 뒤에 '?'를 붙여 사용하게 되면 'return type?' 의 형태로 결과 값을 리턴 받을 수 있게 된다.

위와 마찬가지로? 가 붙은 변수의 경우 기존의 type와 다른 type이므로 return 값도 다른 함수가 호출되는 것이다.

ex) String의 length 메서드의 리턴 형식은 Int , String? 의 length 메서드의 리턴 형식은 Int?

 

4. Elvis연산자

fun main() {
    val a:String? = "hi";
    val size_a3:Int = a?.length ?: -1;
}

위의 Safe Call로 호출한 메서드의 경우 해당 변수가 null 이면 null 값을 return 하게 된다.

만약 호출 시에 Elvis 연사자 (" :? [리턴 값]) 을 추가해주게 된다면 null일 경우에는 정해준 값을 리턴하게 된다.

Elvis 연산자로 호출하는 리턴 값은 해당 메서드가 null이 아닐 경우에 return 하는 형식으로 추가해주어야 한다.

Elvis 연산자가 추가된 메서드 리턴 값은? 가 붙지 않은 변수에 할당 가능하다(null일 가능성이 없는 것으로 판단)

 

5. nullable로 선언했지만 로직상 절대 null이 될 수 없는 변수 처리

fun main() {
    add(1);
    add(null); // NPE 발생
}

fun add(a:Int?):Int
{
    val b:Int = a!!+1;
    return b;
}

변수에 '!!'를 추가하면 코틀린의 null 관련 처리를 무시하고 기존 JAVA 코드처럼 처리되게 할 수 있다.

로직상 절대로 null이 불가능한 상황에서 사용하며 null point exception이 발생할 수 있다.

 

6. JAVA 클래스 사용 시

1) JAVA

public class NullableSomething {

    private final Integer a = 1;

    @Nullable
    public Integer getANullable()
    {
        return a;
    }

    @NotNull
    public Integer getANotNull()
    {
        return a;
    }

    public Integer getANoAnnotaion()
    {
        return a;
    }
}

2) Kotlin 

fun main() {
    val ns = NullableSomething();
    // val get_from_java:Int = ns.aNullable; <- nullable 어노테이션이 붙은 함수는 불가
    val get_from_java:Int = ns.aNotNull
    val get_from_java2:Int = ns.aNoAnnotaion
}

코틀린에서 자바 클래스를 사용하게 될 경우 자바 소스의 어노테이션 기반으로 판단하여 null이 가능한지 아닌지 판단하게 된다.

만약 nullable이 붙어 있는 메서드의 리턴 값을 쓴다고 하면 type?으로 변수를 선언해야 하며

Notnull인 경우에는 일반 type으로 선언이 가능하다( 물론 nullable type으로 선언도 가능)

null 관련 어노테이션이 없는 경우 선언은 가능하되 NPE가 발생할 수 있다.