Kotlin's Null safety to send to Java developers

Nullable and nullable

Kotlin's type system is a type that can be null, Distinguish between types that cannot be. For types that can be null, add ? After the type name.

val num: Int = null //Compile error cannot be null
val num: Int? = null //OK if nullable type

You cannot directly access nullable functions and properties. A compile error will occur.

val num: Int? = null //Declared as nullable type
val floatNum = num.toFloat() //Compile error

Inaccessible if it may be null means The risk of NullPointerException is greatly reduced.

Safe call

You'll often see such null checks in Java.

// Java
Dog dog = //May be null
dog.run(); //Possible NullPointerException Ali
if (dog != null) {
    dog.run(); //Null checked
}  

Let's implement the same in Kotlin.

val dog: Dog? = //May be null
dog.run() //Compile error
if (dog != null) {
    dog.run() //OK for null-checked blocks
}

Functions for nullable objects cannot be called directly. Automatically cast to null-free type in null-checked if blocks You can call the function. This is called a smart cast.

Kotlin also has more convenient syntactic sugar.

val dog: Dog? = //May be null
dog?.run()

You can access function calls and properties after ?.. In the above example, if dog is null, it just returns null. This is called a safe call.

Safety cast

You'll see downcast code like this in Java.

/*
 *Dog class is a subclass of Animal class
 */
Animal animal = // ...

((Dog)animal).run(); //Possibility of ClassCastException Ali

if (animal instanceof Dog) {
    Dog dog = (Dog)animal;
    dog.run();
}

Let's implement the same in Kotlin.

/*
 *Dog class is a subclass of Animal class
 */
val animal: Animal = // ...

(animal as Dog).run() // //Possibility of ClassCastException Ali

if (animal is Dog) {
    animal.run()
}

Kotlin casts use the ʻas` operator. If the cast fails, a ClassCastException will be thrown.

The Java equivalent of ʻinstanceof is the ʻis operator. This is also by smart cast In the if block, the variable ʻanimal` is automatically cast to Dog type, You can call the method of Dog class as it is.

Kotlin also has more convenient syntactic sugar.

val animal: Animal = // ...
(animal as? Dog)?.run()

The ʻas? Operator casts it to the Dog? `Type in the above example. If you can't cast, it will return null, which is safe.

Non-null statement

Besides the safe call (with .?), there is a way to handle nullable types.

val num: Int? = //May be null
val floatNum = num.toFloat() //Compile error
val floatNum = num!!.toFloat() //Compile OK but possible NullPointerException

Add . !!. There are some situations where it is necessary, but it should not be used as much as possible.

Elvis operator

You will often see this kind of branching in Java.

// Java
Dog dog = getDog(); //The return value of getDog may be null
if (dog == null) {
    dog = new Dog();
}
dog.run();

kotlin has a handy operator for "if null".

    val dog = getDog() ?: Dog()
    dog.run()

?: Elvis operator Nullable variables on the left On the right side, describe the process to be executed if it is null. It's common to create an alternate object or throw an Exception.

Non-nullable class property

When declaring a class property, you may have to make it a nullable type. Framework classes that cannot override constructors, Properties that can only be initialized after a certain callback ...

However, they are usually cumbersome to work with nullable types, and you may want to treat them as virtually non-nullable types. (Often actually developed in Kotlin)

In such cases, the lateinit modifier is useful.

//View class for login
class LoginView {
    //It has child elements such as TextView and Button,
    //These are generated from resources...Virtual UI system
    lateinit var emailTextView: TextView
    lateinit var passwordTextView: TextView
    lateinit var loginButton: Button
    
    //Child elements can be retrieved when View is loaded from a resource
    fun onLoadViewFromResource(viewResource: View) {
        this.emailTextView = viewResource.children[0]
        this.passwordTextView = viewResource.children[1]
        this.loginButton = viewResource.children[2]
    }
}

The lateinit modifier can delay initialization, Note that accessing the property before initialization will result in an Exception.

In addition to this, there is a property delegate called lazy. This is useful for deferred initialization of properties that are expensive to initialize.

class LoginView {
    
    val loginConnection: LoginConnection by lazy {
        LoginConnection() //Login Connection is expensive to generate
    }
    
}

Recommended Posts

Kotlin's Null safety to send to Java developers
Kotlin Class to send to Java developers
Kotlin scope functions to send to Java developers
Kotlin's improvements to Java
Kotlin functions and lambdas to send to Java developers
Getting started with Kotlin to send to Java developers
How to write modern Java. Immutable Java, consider Null safety.
[Java] Convert Object type null to String type
[Java] How to test for null with JUnit
I want to send an email in Java.
[Java] Introduction to Java
JAVA NULL checker
Introduction to java
Send me a roadmap to becoming a full-fledged Java engineer
[Null safety] Kotlin Java comparison memo Correct use of Null safety
Changes from Java 8 to Java 11
Sum from Java_1 to 100
[Java] Connect to MySQL
Java null coalescing operator
From Java to Ruby !!
Introduction to java command
Java Library-Alibi Cloud's LOG Java Producer helps send data to log services