Nullability in Kotlin
Kotlins approach is to convert the well known Javas NullPointerException from runtime to compile-time error. By supporting nullability, the compiler can detect possible errors during the compilation, reducing runtime errors.
Marking a variable or property as nullable type, is a way of indicating that they are allowed to be null. In other words, if a variable can be null, calling a method on it isn’t safe. Kotlin disallows such calls.
If you don’t expect String s to be null, define the following;
Calling strLen on null will be flagged as a compile error.
If you want to allow the use of this method on null values as well, you need to mark it by adding a question mark after the type name (marking it nullable):
To sum up, if you don’t mark the variable as nullable, compiler understands that you don’t expect the value to be null. Compiler will complain if you’re trying to pass a nullable type to a function expecting a non null parameter. It enforces you to compare the variable with null value (deal with it in case null), once you do that, compiler remembers that and treats the value as being non-null in the scope where the check has been preformed.
Depending on how you want to handle the possible null value, you can use the following operators:
String -> calling a not null-safe operation with an argument that might be null isn’t allowed and will be flagged by compiler
String? -> the set of operations you can perform on it is restricted by compiler and in case you wan’t to pass a nullable value, you’re forced to deal with it (compare it will null value -> compiler will remember that and treat the value as non-null in the scope)
String?. -> (Safe-Call Operator) if the value on which you’re trying to call the method isn’t null, the method is executed normally, else call is skipped and null is returned
String?: -> (Elvis Operator, also Non-Coalescing Operator) this operator takes two values, and its result is the first value if it isn’t null or second if the first one is null
String!! -> (Non-Null Assertion) – for null values an exception is thrown
?.let -> (Let Function together with Safe-Call Operator) – Let Function is called only for non-null values, else nothing happens
Java and nullability
Java has some tools to help solve the problem of NPE. For example annotations @Nullable an @NotNull combined with tools that can use these annotations to detect places where a NPE can be thrown. But such tools aren’t part of the standard Java compilation process, so it’s hard to ensure that they are applied consistently. Another way to solve NPE problem in Java is to avoid null values all together. Use Optionals introduced in Java 8 or Null Object Design Pattern.
@Nullable String -> seen as String? in Kotlin
@NotNull String -> seen as String in Kotlin
When annotations aren’t present, Java type becomes a platform type in Kotlin. A platform type is a type for which Kotlin doesn’t have nullability information – you can treat it as nullable or non-null type. This means you carry the full responsibility for the operations you perform with this type (just as in Java). Compiler will allow all operations. Just as in Java, you’ll get a NPE if you perform a not null-safe operation on a null value.
We could avoid null checks if Kotlin would treat all incoming values from Java as nullable, but we would end up with large amount of redundant null checks for values that can never be null, hence Kotlin designers came up with platform types.
Note that you can’t declare platform types in Kotlin, they can only come from Java. String! anotation is how the Kotlin compiler denotes platform types, it emphasises that the nullability of the type is unknown. You can’t use this syntax in your Kotlin code.