Java code can pass information about nullability using annotations:
- @Nullable String -> seen as String? in Kotlin
- @NotNull String -> seen as String in Kotlin
Kotlin recognises many different flavours of nullability annotations, e.g. packages javax.annotation, org.jetbrains.annotations, android.support.annotation,… (click here for more info about nullability 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! notation 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.
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