Empty type

The biggest difference between Kotlin and Java is probably the empty type. With Kotlin, the IDE will intelligently warn you of errors that might be empty, and the developer will have to handle the error or the compiler will fail. This reduces the likelihood of NullPointException, so Kotlin development typically sees very few NPE exceptions.

Non-null and nullable types

fun getName(a): String {
    return "lqr"
}
Copy the code

This is a very common function declaration that specifies that the function returns a String, which Kotlin would say is a function that can’t return null, so what if I just want to return NULL?

IDE error: Null can not be a value of a non-null type String
fun getName(a): String {
    return null
}
Copy the code

The IDE error indicates that the function return value type String is a value that cannot be null, that is, a non-null type. If you want the function to return NULL, you need to make a small change to the function return value type so that it can be null. This simply appends? You can:

fun getName(a): String? {
    return null
}
Copy the code

To sum up, Kotlin’s type declarations fall into two categories (including but not limited to function return value types) :

  • Nonempty types: Classes that are simply declared are nonempty types, such as:String.
  • Nullable type: by placing it after the class?To declare, as:String?.

Nullable type operator

This section focuses on three of the operators Kotlin provides for null-safe code.

Learn more Kotlin empty safety knowledge, please visit: www.kotlincn.net/docs/refere.

Safe call operator (? .)

For example, to get the length of a string, a non-null variable can be passed directly through.length:

val name: String = "lqr"
println(name.length)
Copy the code

Nullable type variables are not only used in type declaration, right? Is also required when calling length, the member variable of a nullable type object? . To process:

val name: String? = nullprintln(name? .length)// Output: null
Copy the code

Since the value of name is null,.length is not executed, so this code is equivalent to println(null). The result is null, but the program does not crash.

The safe call operator (? .). : calls a method or accesses a property if the receiver is not empty, otherwise not executed.

Elvis operator (? :)

In daily development, we often use a single line of code to handle both non-empty and empty variables. In Kotlin, if-else code is used to write:

println(if(getName() ! =null) getName() else "Default Name")
Copy the code

Java has ternary operators and Kotlin doesn’t, so you can only use if-else here.

Kotlin also provides the Elvis operator (? If else :);

println(getName() ? :"Default Name")
Copy the code

The Elvis operator (? 🙂 : If? The Elvis operator returns the left-hand expression if it is not empty, or the right-hand expression if it is not. Note that the right-hand side of the expression is evaluated if and only if the left-hand side is empty.

Non-empty assertion operators (!!!!!)

If you are very, very sure that the value of a variable can never be null, then you can use it on object calls!! Convert it to a non-null type:

val value: String? = "Hello LQR"println(value!! .length)Copy the code

Non-empty assertion operators (!!) : Converts any value to a non-null type and throws an exception if the value is null.

Intelligent type conversion

Type conversions are common in development, especially in polymorphic application scenarios, where superclass variables are used to receive subclass objects and may need to be forcefully cast to a specific subclass type to use specific subclass functionality.

open class Parent {}

class Child : Parent() {
    fun getName(a): String {
        return "lqr"}}fun main(args: Array<String>) {
    val man: Parent = Child()
    println((man as Child).getName())
}
Copy the code

In Kotlin, strong transitions need to be handled using the AS keyword.

Of course, the code here is very bad to handle, usually before the conversion will determine the specific type of the object and then strong, in order to avoid type conversion exceptions, so the code can be changed to:

val man: Parent = Child()
if (man is Child) {
    println(man.getName())
}
Copy the code

Kotlin uses the is keyword to determine the type of the variable. In the if block, the man variable is already recognized as a Child, so there is no need for explicit coercion.

Parent man = new Child();
if (man instanceof Child) {
    System.out.println(((Child) man).getName());
}
Copy the code

Back to the AS keyword, the Kotlin code uses AS to force the type of an object. If we force the type of a variable without first checking the type, we must throw a ClassCastException if the object is of the wrong type:

// Exception in thread "main" java.lang.ClassCastException: com.charylin.kotlinlearn.Parent cannot be cast to com.charylin.kotlinlearn.Child
val parent: Parent = Parent()
val child: Child = parent as Child
print(child)
Copy the code

Fortunately, Kotlin’s smart casting provides a way out of “direct strong casting” using as? If a variable has an explicit type, change it to nullable, or remove the variable type declaration altogether:

val parent: Parent = Parent()
val child: Child? = parent as? Child
// val child = parent as? Child// is also OKprint(child)// Output: null
Copy the code

as? A bit smarter than AS, the result will be null if there is a misunderstanding of the force type.