Archives
Recent Posts
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[16일차 Kotlin] Null 처리(!! 연산자, ?: 연산자, ?. 연산자) 본문

Computer/Kotlin

[16일차 Kotlin] Null 처리(!! 연산자, ?: 연산자, ?. 연산자)

Wise-99 2023. 5. 20. 01:38

 

 

출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT

 

 

 

📖 Null 처리

NullPointerException

  • 객체의 주소 값이 담겨져 있지 않는 (null 값이 들어있는) 참조 변수를 통해 객체 접근을 시도하면 발생되는 오류이다.

null safe

  • Kotlin 은 개발자가 null이 담겨 있는 참조변수를 통해 객체 접근을 시도할 때 오류가 발생되는 것을 방지하고자 다양한 방법을 제공하고 있다.
  • 이를 통해 null 값에 대한 안정성을 확보(null safe)할 수 있다.

!! 연산자

  • !! 연산자는 null을 허용하는 변수에 담긴 객체의 주소 값을 null을 허용하지 않는 형태의 값으로 변환하는 연산자이다.
  • null을 허용하는 변수에 담긴 값을 null을 허용하지 않는 형태의 변수에 담을 경우 사용한다.
  • 변환 과정에서 null 값이 들어 있을 경우 오류가 발생한다.

?: 연산자

  • ?: 연산자는 참조변수에 null 이 들어있으면 지정된 기본값을 반환한다.

?. 연산자

  • 참조변수를 통해 메서드를 호출하거나 멤버 변수를 사용할 때 참조변수에 객체의 주소값이 들어 있다면 객체에 접근해서 메서드나 변수를 사용한다.
  • 만약 참조변수에 null이 들어 있다면 오류가 발생하지 않고 null을 반환한다.

 

 

 

📖 예제 코드

 !! 연산자 예제 코드

fun main(){
    testFun1("안녕하세요")
    testFun1(null)      <<< 오류 발생
    
    var t100 = TestClass1(100,"문자열1")
    testFunction100(t100)
    testFunction100(null) <<< 오류 발생
}

fun testFun1(str1:String?){
    val value1:String = str1!!
    println("value1 : $value1")
}

fun testFunction100(t1:TestClass1?){
    println("t1.str1 : ${t1!!.str1}")
    println("t1.str2 : ${t1!!.str2}")
    t1!!.testMethod1()
}

✔️ 코드 해석

  • fun testFun1(str1:String?){ ... }
    • str1을 !! 연산자를 사용하여 null을 허용하지 않는 타입으로 변환한다.
    • 매개변수로 null을 넣으면 오류가 발생한다.
  • fun testFunction1(t1:TestClass1?){ ... }
    • !! 연산자는 null을 허용하는 변수에 담긴 값을 추출하여 null을 허용하지 않는 타입으로 반환하는 연산자이다.
    • 이에 null 값이 들어있으면 오류가 발생한다.
    • null 안전성울 확보하지 않고 멤버에 접근하겠다면 !!를 붙여준다.

 


?: 연산자 예제 코드

fun main(){
    testFun2("안녕하세요")
    testFun2(null)
}

fun testFun2(str1:String?){
    val value1:String = str1 ?: "기본문자열"
    println("value1 : $value1")
}

✔️ 코드 해석

  • str1 에 null 아닌 객체의 ID가 들어있으면 그 ID를 value1 변수에 담아준다.
  • null이 있으면 지정한 값인 "기본문자열"이 value1 변수에 담긴다.

 


?. 연산자 예제 코드

fun main(){
    var a1:String? = null
    var a2:String = null <<< 오류 발생
    
    testFun3("안녕하세요")
    testFun3(null)
    
    var t200 = TestClass1(200,"문자열2")
    
    testFunction200(t200)
    testFunction200(null)
    
    testFuntion300(t100)
    testFuntion300(null)
}

fun testFun3(str1:String?){
    if(str1 != null){
        val value1:String = str1
        println("value1 : $value1")
    }
}

fun testFunction200(t1:TestClass1?){
    println("t1.str1 : ${t1?.str1}")
    println("t1.str2 : ${t1?.str2}")
    t1?.testMethod1()
}

fun testFuntion300(t1:TestClass1?){
    if(t1 != null){
        println("t1.str1 : ${t1.str1}")
        println("t1.str2 : ${t1.str2}")
        t1.testMethod1()
    }
}

✔️ 코드 해석

  • var a1:String? = null
    • null을 허용하는 변수를 선언할 때 자료형 뒤에 ? 연산자를 붙인다.
    • ? 연산자를 사용하지 않은 변수에 null을 넣으면 오류가 발생한다.
  • fun testFun3(str1:String?){ ... }
    • 만약 변수의 값이 null인 경우 코드가 동작하지 않도록 처리해주면 null 안정성을 확보할 수 있다.
    • 이때, null을 허용하는 변수를 null을 허용하지 않는 변수처럼 자유롭게 사용할 수 있다.
  • testFunction200(t1:TestClass1?){ ... }
    • 참조변수?.멤버변수 : 참조변수에 null 값이 들어있다면 null 이 반환된다.
    • 참조변수?.멤버 메서드 : 참조변수에 null 값이 들어있다면 메서드를 호출하지 않는다.
  • testFunction300(t1:TestClass1?){ ... }
    • null 이 저장되어 있는지 여부를 확인한다.
    • if 문 내부에서는 null을 아무런 연산자도 붙이지 않고 멤버 접근이 가능하다.