Null Safety

Updated:

  • Null Safety

    • Kotlin에서는 기본적으로 안전한 null 사용 방법을 제공 하고 있고, Null safety 문서에 따르면 ‘The Billion Dollar Mistake’ 이라고 알려진 코드에서 null 참조의 위험을 제거 하는 것을 목표로 한다 라고 쓰여져있다.

    • Kotlin에서는 Null을 변수 자체에 단순하게 할당이 불가능하다.

      var a:String = "30"
      a = null // error
      
    • 여기서 변수를 선언 할 때 ? 을 붙여 주면 null을 참조 할 수 있게 된다.

      var b: String = "str"
      b = null // ok
      print(b) // null
      
    • 또한 메소드를 호출하거나 할 때 위의 예제에서는 a에 관한 메소드는 사용이 가능하지만

      b에 대한 메소드는 안전하지 않기 때문에 컴파일러에서 error라고 알려준다

      val l = a.length // ok
          
      val l = b.length // error
      

      따라서 null 의 상태를 체크 한 다음에 메소드를 호출 하면 된다.

      val l = if(b!=null) b.length else -1
          
          
      //another example
      val b: String? = "Kotlin"
      if (b != null && b.length > 0) {
          print("String of length ${b.length}")
      } else {
          print("Empty string")
      }
      
    • Safe Calls - kotlin에서 제공하는 방법으로 nullable 한 변수를 검사하여 안전하게 호출하도록 해주는 연산자 ?. 을 붙여 메소드를 호출한다.

      val a = "Kotlin"
      val b: String? = null
      println(b?.length)
      println(a?.length) // Unnecessary safe call
      
    • Elvis Operator

      코드를 작성시에 null 인 경우 default 값을 주고 싶은 경우 사용 하는 연산자로 ?: 을 이용한다.

      val l: Int = if (b != null) b.length else -1
          
      //위의 코드를 아래 와 같이 사용 하면 단축하여 사용 할 수 있다.
      val l = b?.length ?: -1
      
    • !! Operator - not-null 연산자로 해당 하는 변수가 절대 null 이 아님을 보장하고, 컴파일러가 해당 코드를 그냥 수행 하며 만일 null 일 경우에는 NPE 를 throw 한다.

      val l = b!!.length
      
    • Smart Cast

      스마트 캐스트 인 is 를 이용하면 as 를 사용하지 않고도 type을 변환 할 수 있다.

      as를 바로 사용하여 casting 할 때 대상 유형이 아닌경우 ClassCastExceptioin 이 발생할 수 있기에

      as? 를 지원한다.

      //casting 이 불가능 할 경우 null을 반환한다.
      val aInt : Int ? = a as? Int
      
    • Collections of Nullable Type

      만약 nullable type 의 collection에서 non-null 인 요소들을 이용하려면 filterNotNull 을 사용하면 된다.

      val nullableList: List<Int?> = listOf(1, 2, null, 4)
      val intList: List<Int> = nullableList.filterNotNull()
          
      for(element in intList){
      	print(element + " ")
      }//1 2 4