Kotlin의 Null Safety에서 고민했던 이야기.

입문


  • 본 보도는 아래 환경에서 동작을 확인하였다.
  • Android Studio 3.0
  • Kotlin 1.1.51
  • compileSdkVersion25 및 26
  • 본 보도는 Kotlin Advent Calendar 2017 14일째 보도입니다.
  • *자바만 써본 사람이라도 쉽게 쓸 수 있을 것 같아서...


    무엇이 빈 안전입니까


    "Null Safety? 알아요!"이런 사람은 건너뛰세요.
    Java와 달리 Kotlin은 기본적으로 null을 사용할 수 없습니다.
    기본적으로 대상이 non nullable이기 때문이다.
    예를 들어 아래의 코드는 오류입니다.
    test.kt
    val sampleStr: String  = "Kotlin"
    println(sampleStr)
    sampleStr = null
    

    그럼 null을 사용하려면 어떻게 해야 하나요?
    답안은 아래와 같다.
    test.kt
    var sampleStr: String?  = "Kotlin"
    println(sampleStr)
    sampleStr = null
    println(sampleStr)
    

    String?유형은 문자열 유형과 완전히 다른 클래스입니다.
    이것은 아래의 코드를 통해 확인할 수 있다.
    test.kt
    val sampleStr1: String   = "Kotlin"
    var sampleStr2: String?  = null
    println(sampleStr1 is Any)
    println(sampleStr2 is Any)
    

    Any 정보
    Java 프로그래머가 Kotlin에서 넘어지기 쉬운 곳에 있어요.
    상세하다.

    정말 Null Safety인가요?


    Kotlin에서 nullable인지 아닌지를 똑똑히 알 수 있다.
    그러면 컴파일할 때nullable인지 아닌지 똑똑히 알 수 있습니다
    이제 Null Pointer Exception과 작별을 고했습니다!응, 시원해!
    안 갔어요.
    아래 코드를 보십시오.
    extension.kt
    fun <T : View> View.bindView(@IdRes id: Int): Lazy<T> = lazy {
        findViewById(id) as T
    }
    
    SampleView.kt
    class SampleView : FrameLayout{
        constructor(context: Context?) : super(context)
    
        constructor(context: Context?,
                    attrs: AttributeSet?) : super(context, attrs)
    
        constructor(context: Context?,
                    attrs: AttributeSet?,
                    defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    
        constructor(context: Context?,
                    attrs: AttributeSet?,
                    defStyleAttr: Int,
                    defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
    
        private val profileImageView: ImageView by bindView(R.id.profile_image_view)
        private val titleTextView   : TextView  by bindView(R.id.title_text_view)
        private val userNameTextView: TextView  by bindView(R.id.user_name_text_view)
    
        // (以下略)
    
    상술한 코드가 뜻밖에도 컴파일을 통과했다.
    뭐가 문제야?

    사실 findView ById는 nullable입니다.
    ID를 확실히 지정하면 문제가 없지만 잘못된 값을 넣으면...

    아!(비명 지르기)
    그렇습니다.

    진짜 Null Safety 아니에요?


    이 기사에서 나는 실험을 하면서 여기서 어떻게 Null Pointer Exception을 일으키는지 기록하고 싶다
    실제로 2017년 11월 10일까지 Android SDK 측은 대응했다.
    AndroidO의 findViewById 사양 변경
    광고 달력 2017, 내일은 kamedon39.

    참조 URL


    Java 프로그래머가 Kotlin에서 넘어지기 쉬운 곳에 있어요.
    AndroidO의 findViewById 사양 변경

    좋은 웹페이지 즐겨찾기