Search code examples
kotlintype-systems

What is the meaning of Type! in Kotlin?


I'm very aware of the Kotlin null safeness. I Know "?" after a type (ex: Int?) can be used to declare a variable or value as nullable. I also know that !! operator is used to return a non-null value or throw NPE.

In general, a type with "?" after it will be nullable, and without "?" is a non-null. But I have seen when I'm inspecting some variables something like this:

var myVariable: Int!

It happens when you use java code from kotlin code.

//java code
public class Foo {
    public Integer calcNumber()
    {
        return null;
    }
}

If I use the function Foo.calcNumber()

//kotlin code
val meh = Foo().calcNumber()
print(meh)

the value meh is inspected as Int!, not Int nor Int?. Obviously here the value meh can be null, but it is not correctly "detected" by the "IDE".

As

var a: Int! = 10

is invalid, my question is: What does exactly mean types with "!"?


Solution

  • The Type! notation is called a Platform Type and is critical for Interoperability with the weaker-typed Java; it means "the null-ability is unknown" and it allows for relaxed null-ability enforcement. I found the examples in the linked question underwhelming.. although all the information is there.

    The following program is accepted as type-safe, as Kotlin allows the type of the x/Int! expression to be used as "Int or Int?".

    var x = JavaIntegerList.get(0); // Int! type inferred by Kotlin
    var y: Int? = x;
    var z: Int = x;
    

    However, the assignment to z (Int) will fail at run-time if x evaluates to null. (For class implementation types, the NPE may delayed to usage: basically, Kotlin chooses to 'get out of the way'.)

    It's thus designed for cases when it is known that the value "cannot" be null in a valid program, although the value comes from Java outside of the Kotlin type system. Highly applicable to int-box-Integer in Java, although it is valid for any class type / value coming in from Java. If the Java code can return null, it is safest to put the value into a Type? immediately and then correctly deal with the null-ability.

    Compare this to the Java code with similar run-time failure semantics:

    // Java
    Integer x = JavaIntegerList.get(0);
    Integer y = x;  // "No OP" - all class types in Java are null-able
    int z = (int)x; // kaboom *at run-time* if x is null!
    

    While simple to show with ints, as in this example, this issue is not strictly related to Java's int/Integer types. The document linked above shows a case of String! being implicitly used, giving the example that item.substring(1), where item is a String! is allowed/type-safe but will fail at run-time if item evaluates to null.