

Variablename = null // It shows the compilation error

Var variablename: datatype = values // It is the regular initialization it accepts non-null values by default In generated bytecode former method takes int while the latter development, programming languages, Software testing & others fun main() Interestingly primitives can also be nullable:įun unsafePositive(x: Int?): Boolean = x != null & x > 0 Val str: String = "Hello" //String type can be inferred here In other words we can pass type T when T? is required - which is quite obvious: Just like in any other polymorphic language upcasting is implicit. I said a lot about downcasting, remembering that any non-null type T has a super type of nullable T?. The compiler can prove that obj is actually of type String so it performs automatic, safe downcasting for us.

See? obj is of type Any ( Object in Java terms) so calling hello(obj) is doomed to fail, right? Not quite. Not in Kotlin: val obj: Any = "Any object" Similarly I always found it annoying in Java that after using instanceof operator (being annoying on its own) I still have to down cast my object: To be precise, the compiler can prove that downcasting from String? to String is safe. because we just checked for null, compilation succeeds. However if the compiler can prove that a call is safe, e.g. The compiler prevents us from calling hello() with String? due to incompatible type. However we explicitly declare maybeStr as String? type (nullable String). Function hello() accepts String so hello(str) is fine. In the syntax layer each type T has a super type T? that allows null. We get NullPointerException-free code and no runtime overhead due to extra Optionwrapper. References that can be null have different type, thus null-safety is encoded in the type system and enforced only during compilation.

