A non-nullable type is Kotlin’s default: `String`, `Int`, and `MyType` cannot hold `null`. Add `?` only when absence is a valid value, as in `String?`. This distinction prevents code from treating a possibly absent value as though it were ready to use. section 7.2 section 7.3
Require a present string
```kotlin fun strLen(s: String) = s.length fun main() { strLen(null) // error } ``` Because `s` is non-nullable, callers cannot pass `null`, and `length` needs no null check. A `String?` cannot be assigned to `String` or passed where `String` is required. After checking `s != null`, Kotlin treats a nullable value as non-nullable within that checked scope. section 7.2
Use the type distinction to make null handling explicit:
- Declare a parameter or property non-nullable when it must have a value; provide an initializer for non-nullable properties unless delayed initialization is appropriate. section 7.2 section 7.9
- Handle `T?` before calling members or passing it to a non-nullable parameter, using an `if` check or a safe-call with `let`. section 7.2 section 7.8
- Treat `T` as usable where `T?` is expected, but not the reverse: a non-null type is a subtype of its nullable version. section 11.3.2
- Constrain a generic parameter with `<T : Any>` when substitutions must be non-null; unconstrained `T` can be nullable. section 11.1.4 section 7.11
Pass a nullable value safely
```kotlin fun sendEmailTo(email: String) { println("Sending email to $email") } val email: String? = "yole@example.com" email?.let { sendEmailTo(it) } ``` The safe call runs `let` only when `email` is present. Inside the lambda, `it` is suitable for `sendEmailTo`, which requires a non-nullable `String`. section 7.8
Nullable and non-nullable values use the same runtime objects rather than wrapper objects, with little runtime overhead beyond generated intrinsic checks. The main protection is therefore at compile time: disallowed operations and unsafe flows are rejected before execution. section 7.3
Listing 7.19 Implementing the Java interface with different parameter nullability
class StringPrinter : StringProcessor {
override fun process(value: String) {
println(value)
}
}
class NullableStringPrinter : StringProcessor {
override fun process(value: String?) {
if (value != null) {
println(value)
}
}
}
Compare two Kotlin implementations of the same Java interface: one accepts `String`, and one accepts `String?`. Choosing `String` causes generated assertions for calls arriving from Java; Java passing `null` then triggers an exception even if the implementation does not read the parameter. section 7.12.2
`lateinit var` is an escape hatch for framework-managed setup: it keeps a property non-nullable without constructor initialization. It shifts responsibility to initialization order; reading the property too early produces a specific uninitialized-property exception. This is useful for patterns such as JUnit setup or Java dependency injection. section 7.9

