Kotlin, a (young) programming language with a so-called null-safe feature, will sometimes declare variables null-able for practical business scenarios, but thanks to the null-safe feature, the compiler forces null-checking on null-able variables (unless you use non-null assertions!!). Force the compiler to shut up. Kotlin’s design principle is full Java compatibility. The designers probably anticipated that users would still need to do a lot of null-checking during the design phase, so they introduced the very elegant Elvis operator. Here’s the code:

Java typical nulls:

/** * <p> What is the length of the string the console prints </> *@paramSTR: the given string */
    public void askStringLength(String str){
        int i;
        // In Java, we usually nullate this way, or use the ternary operator
        if (str == null){
            i = 0;
        } else{
            i = str.length();
        }

        // Or use the ternary operator
        i = str == null? 0 : str.length();

        System.out.println("The length is " + i);
    }
Copy the code

As mentioned above, Java has no such thing as null-safety features. You might need to write a lot of null_template code like the one above, and you certainly can’t put defensive code in every variable that might be empty. After all, it’s easy to accumulate thousands of variables in a project. Of course the compiler will highlight the places where there is a high probability of a null pointer exception being thrown, but the places that do are too small for the overall project. A NullPointerException (NPE) may be thrown at runtime if NullPointerException (NPE) is not NullPointerException (NPE).

Kotlin redesigned a completely different type system from Java, claiming to have significantly fewer NullPointerExceptio in the project (Kotlin couldn’t completely eliminate NPE because he was designed for full Java compatibility). In my own experience, the results are not bad, using Koltin project NPE is much less. And Koltin’s way of null-checking where an NPE might be thrown is far more elegant than Java’s, eliminating all that annoying if-else by using the so-called Elvis operator.

The difference between Kotlin’s type system and Java’s is not the point of this article. The point is that in Kotlin, if a variable is nullable, you cannot access it without checking for nulls (unless you use non-null assertions!!). Force the compiler to shut up)! This makes it much less likely that our code will throw an NPE at runtime! Well, problems that can be found at compile time should not be found at run time! Let’s look directly at the Java code with nulls above and its Koltin equivalent.

Kotlin’s typical call short operation:

/** ** <p> What is the length of the string the console prints </> *@paramSTR: the given string */
    fun askStringLength(str: String?). {
        val i: Int
        // In Kotlin, we usually null variables like this
        / /? . Is what Kotlin calls the secure call operator
        // If STR is not empty, return str.length, otherwise return null, expression (STR? .length) returns type Int? Well, it could be null
        / /? ; It's called 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 noti = str? .length? :0//str.length is not compiled
        If (else) {// If (else) { Note that the Elvis operator in Kotlin is not a ternary operator. There is no ternary operator in Kotlin

        println("The length is $i")}Copy the code

In Kotlin, we usually null variables like this:

i = str? .length? :0
Copy the code

? . Is the so-called safe call operator in Kotlin, which returns str.length if STR is not empty, null otherwise, and the expression (STR? .length) returns type Int? Well, it could be null, right? ; It’s called the Elvis operator. What if? The Elvis operator returns the left side of the expression if it is not empty, otherwise it returns the right side (as the default).

If we had a new requirement to calculate the sum of all the strings in a List, you might write:

/** *<p> The console prints the sum of all the string lengths in the list </> *@paramStrings: given a list of strings */
    fun askStringLength(strings: List<String? >) {
        var i: Int = 0strings.forEach { str -> i = str? .length? :0 + i // Notice this line of code, of course you would be more likely to write I += STR? .length? Zero, just to show you what I wrote
        }
        println("The length is $i")}Copy the code

If it is written as above, you will not get the correct result! You can run it!

The reason is that the Elvis operator has a lower priority. Check out the list below, which I pulled from Kotlin’s website:

Precedence Title Symbols
Highest Postfix ++.--...? ..?
Prefix -.+.++.--.!.label
Type RHS :.as.as?
Multiplicative *./.%
Additive +.-
Range .
Infix function simpleIdentifier
Elvis ? :
Named checks in.! in.is.! is
Comparison <.>.< =.> =
Equality = =.! = =
Conjunction &&
Disjunction ||
Lowest Assignment =.+ =.- =.* =./ =.% =

Notice the location of the Elvis operator!

This line of code:

i = str? .length? :0 + i
Copy the code

It’s equivalent to

i = str? .length ? : (0 + i)
Copy the code

So in order for the code to work correctly, we should write it like this:

i = (str? .length? :0) + i
Copy the code

Pay attention to the precedence of the operator when using it!

That’s all.