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

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).
主站蜘蛛池模板: 石台县| 都匀市| 合作市| 正蓝旗| 越西县| 芦山县| 湾仔区| 河间市| 赣榆县| 温州市| 河津市| 图木舒克市| 连平县| 满城县| 师宗县| 临海市| 白朗县| 无棣县| 城步| 宜春市| 肥东县| 雷州市| 斗六市| 永定县| 西畴县| 庆元县| 汶上县| 兴义市| 宣武区| 新巴尔虎左旗| 麟游县| 双柏县| 红河县| 普定县| 久治县| 理塘县| 丽江市| 库车县| 香河县| 大港区| 吉林市|