官术网_书友最值得收藏!

Nullability and Java

We know that Kotlin requires us to explicitly define references that can hold null values. Java on the other hand is much more lenient about nullability, so we may wonder how Kotlin handles types coming from Java (basically the whole Android SDK and libraries written in Java). Whenever possible, the Kotlin compiler will determine type nullability from the code and represent types as actual nullable or non-nullable types using nullability annotations.

The Kotlin compiler supports several flavors of nullability annotations, including:
  • Android (com.android.annotations and android.support.annotations)
  • JetBrains (@Nullable and @NotNull from the org.jetbrains.annotations package)
  • JSR-305 (Javax.annotation)
We can find the full list in the Kotlin compiler source code (https://github.com/JetBrains/kotlin/blob/master/core/descriptor.loader.Java/src/org/jetbrains/kotlin/load/Java/JvmAnnotationNames.kt).

We have seen this previously in Activity's onCreate method, where the savedInstanceState type was explicitly set to the nullable type Bundle?:

    override fun onCreate(savedInstanceState: Bundle?) { 
        ...
}

There are, however, many situations where it is not possible to determine variable nullability. All variables coming from Java can be null, except ones annotated as non-nullable. We could treat all of them as nullable and check before each access, but this would be impractical. As a solution to this problem, Kotlin introduced the concept of platform types. These are types that comes from Java types with relaxed null checks, meaning that each platform type may be null or not.

Although we cannot declare platform types by ourselves, this special syntax exists because the compiler and Android Studio need to display them sometimes. We can spot platform types in exception messages or the method parameters list. Platform type syntax is just a single exclamation mark suffix in a variable type declaration:

View! // View defined as platform type

We could treat each platform type as nullable, but type nullability usually depends on context, so sometimes we can treat them as non-nullable variables. This pseudo code shows the possible meaning of platform type:

    T! = T or T? 

It's our responsibility as developers to decide how to treat such types, as nullable or non-nullable. Let's consider the usage of the findViewById method:

    val textView = findViewById(R.id.textView)  

What will the findViewById method actually return? What is the inferred type of the textView variable? Nullable type (TestView) or not nullable (TextView?)? By default, the Kotlin compiler knows nothing about the nullability of the value returned by the findViewById method. This is why the inferred type for TextView has the platform type View!.

This is the kind of developer responsibility that we are talking about. We, as developers, must decide, because only we know if the layout will have textView defined in all configurations (portrait, landscape, and so on) or only in some of them. If we define a proper view inside the current layout, the findViewById method will return a reference to this view, and otherwise it will return null:

    val textView = findViewById(R.id.textView) as TextView // 1 
    val textView = findViewById(R.id.textView) as TextView? // 2 
  1. Assuming that textView is present in every layout for each configuration, textView can be defined as non-nullable.
  1. Assuming that textView is not present in all layout configurations (for example, it is present only in landscape), textView must be defined as nullable, otherwise the application will throw a NullPointerException when trying to assign null to a non-nullable variable (when the layout without textView is loaded).
主站蜘蛛池模板: 威海市| 萨迦县| 聊城市| 三亚市| 广昌县| 连江县| 溆浦县| 武威市| 自贡市| 佛学| 元江| 罗源县| 正镶白旗| 安平县| 怀宁县| 肇庆市| 佛冈县| 阜南县| 泉州市| 湘西| 石棉县| 临桂县| 邢台县| 石家庄市| 大兴区| 苗栗市| 中宁县| 渝北区| 维西| 德令哈市| 内乡县| 新竹市| 宜春市| 林周县| 孝昌县| 新昌县| 田阳县| 宁蒗| 赤壁市| 乐业县| 北流市|