Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions concepts/nullability/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"authors": [
"colinleach"
],
"contributors": [],
"blurb": "Kotlin provides optional nullable types, plus functionality to make nullability safe and convenient to use."
}
106 changes: 106 additions & 0 deletions concepts/nullability/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# About Nullability

In an ideal world, we could rely on everything being nicely defined, with concrete values and no gaps.

This conflicts with our everyday experience, and thus many programming languages have a way to represent the absence of a value: null or NULL, nil, None, nothing...

This was easy to introduce (back in 1965), but soon led to regrets.
The inventor later called it his ["Billion Dollar Mistake"][web-mistake].

In recent decades, language designers have explored many ways to make nulls available but (mostly) safe.

Kotlin has a few [general principles][ref-null-safety], which [differ significantly from Java][ref-java2kotlin].
_The differences mean that Kotlin has special functionality to deal with Java interop, though details are beyond the scope of this Concept._

- Kotlin has a special `null` value.
- All types _default_ to being non-nullable (i.e. can not be `null`) .
- All types can be _nullable_, but this must be explicitly done.
- Functions which might fail with an exception are likely to have a variant with a nullable return value.
- Special, highly terse syntax tries to make testing for and responding to nulls as easy as possible.

## Creating nullable variables

A type can be made [nullable][ref-nullable-type] by adding the `?` suffix (e.g. `String?` instead of `String`).

```kotlin
var a = "Kotlin" // inferred type is String
a = null // => Error: Null can not be a value of a non-null type String

var b: String? = "Kotlin" // nullable type
b = null // => b is now null
b == null // => true
```

## Useful operators and functions

### The [safe call operator][ref-safe-call] `?.`

For a non-nullable `String`, we can get the `.length` property.

A nullable `String?` fails with the same syntax, but using `?.length` allows for the possibility of a `null`.
The return type is `Int?`.

```kotlin
var a = "Kotlin"
a.length // => 6

// b is still null
b.length // => Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
b?.length // => null
a?.length // => 6
```

As we saw in the last line above, `?.` also works with non-nullable types.

### The [Elvis operator][ref-elvis] `?:`

Extending the idea of the safe-call operator, the [Elvis operator][wiki-elvis] lets us supply a default value to replace `null`.

```kotlin
// b is still null
b?.length ?: -1 // => -1, in place of null
a?.length ?: -1 // => 6, as before
```

### [Not-null assertion operator][ref-not-null] `!!`

With this operator, a nullable type is forced to be treated as non-null, when the programmer is confident about this.
Perhaps we sometimes understand the program logic better than an over-cautious compiler?

```kotlin
// b is still a String?
b = "Kotlin?"
b!!.length // => 7
```

The responsibility is now on us: if `b` is still `null` we get a `NullPointerException`.

### [Let function][ref-let] `?.let`

If passing a nullable item to a block of code, we could do specific null checks `if (item != null) { do something }`.

It is simpler and more idiomatic to use `item?.let { do something }`,
The `do something` will only execute when `item` is not null.

### Functions of type `somethingOrNone()`

Some functions may fail, for example when asking for an invalid index in a string or list.

Rather than throwing an exception, we could use the [`...OrNull` variant][ref-elem-at-or-null] of the function, to get (in this case) an `Int?` return value.

```kotlin
val str = "Kotlin"
str.elementAtOrNull(10) // => null
str.elementAt(10) // => StringIndexOutOfBoundsException: String index out of range: 10
```

[ref-java2kotlin]: https://kotlinlang.org/docs/java-to-kotlin-nullability-guide.html
[web-mistake]: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/
[ref-null-safety]: https://kotlinlang.org/docs/null-safety.html
[ref-elvis]: https://kotlinlang.org/docs/null-safety.html#elvis-operator
[wiki-elvis]: https://en.wikipedia.org/wiki/Elvis_operator
[ref-nullable-type]: https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-nullable-types
[ref-safe-call]: https://kotlinlang.org/docs/null-safety.html#safe-call-operator
[ref-not-null]: https://kotlinlang.org/docs/null-safety.html#not-null-assertion-operator
[ref-let]: https://kotlinlang.org/docs/null-safety.html#let-function
[ref-elem-at-or-null]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/element-at-or-null.html
100 changes: 100 additions & 0 deletions concepts/nullability/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Introduction

In an ideal world, we could rely on everything being nicely defined, with concrete values and no gaps.

This conflicts with our everyday experience, and thus many programming languages have a way to represent the absence of a value: null or NULL, nil, None, nothing...

This was easy to introduce (back in 1965), but soon led to regrets.
The inventor later called it his "Billion Dollar Mistake".

In recent decades, language designers have explored many ways to make nulls available but (mostly) safe.

Kotlin has a few [general principles][ref-null-safety], which differ significantly from Java.


- Kotlin has a special `null` value.
- All types _default_ to being non-nullable.
- Most types can be _made_ nullable, but the programmer must explicitly order this.
- Functions which might fail with an exception are likely to have a variant with a nullable return value.
- Special, highly terse syntax tries to make testing for and responding to nulls as easy as possible.

## Creating nullable variables

Standard types generally have a nullable equivalent, with a `?` suffix: for example `String?` instead of `String`.

```kotlin
var a = "Kotlin" // inferred type is String
a = null // => Error: Null can not be a value of a non-null type String

var b: String? = "Kotlin" // nullable type
b = null // => b is now null
b == null // => true
```

## Useful operators and functions

### The safe call operator `?.`

For a non-nullable `String`, we can get the `.length` property.

A nullable `String?` fails with the same syntax, but using `?.length` allows for the possibility of a `null`.
The return type is `Int?`.

```kotlin
var a = "Kotlin"
a.length // => 6

// b is still null
b.length // => Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
b?.length // => null
a?.length // => 6
```

As we saw in the last line above, `?.` also works with non-nullable types.

### The Elvis operator `?:`

Extending the idea of the safe-call operator, the [Elvis operator][wiki-elvis] lets us supply a default value to replace `null`.

```kotlin
// b is still null
b?.length ?: -1 // => -1, in place of null
a?.length ?: -1 // => 6, as before
```

### Not-null assertion operator `!!`

With this operator, a nullable type is forced to be treated as non-null, when the programmer is confident about this.
Perhaps we sometimes understand the program logic better than an over-cautious compiler?

```kotlin
// b is still a String?
b = "Kotlin?"
b!!.length // => 7
```

The responsibility is now on us: if `b` is still `null` we get a `NullPointerException`.

### Let function `?.let`

If passing a nullable item to a block of code, we could do specific null checks `if (item != null) { do something }`.

It is simpler and more idiomatic to use `item?.let { do something }`,
The `do something` will only execute when `item` is not null.

### Functions of type `somethingOrNone()`

Some functions may fail, for example when asking for an invalid index in a string or list.

Rather than throwing an exception, we could use the `...OrNull` variant of the function, to get (in this case) an `Int?` return value.

```kotlin
val str = "Kotlin"
str.elementAtOrNull(10) // => null
str.elementAt(10) // => StringIndexOutOfBoundsException: String index out of range: 10
```


[web-mistake]: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/
[ref-null-safety]: https://kotlinlang.org/docs/null-safety.html
[wiki-elvis]: https://en.wikipedia.org/wiki/Elvis_operator
10 changes: 10 additions & 0 deletions concepts/nullability/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"url": "https://kotlinlang.org/docs/null-safety.html",
"description": "Kotlin introduction to null safety."
},
{
"url": "https://kotlinlang.org/docs/java-to-kotlin-nullability-guide.html",
"description": "Nullability guide for Java to Kotlin migration."
}
]
5 changes: 5 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,11 @@
"uuid": "168827c0-4867-449a-ad22-611c87314c48",
"slug": "conditionals",
"name": "Conditionals"
},
{
"uuid": "98809a4c-ca3e-4504-b723-aff13bfae850",
"slug": "nullability",
"name": "Nullability"
}
],
"key_features": [
Expand Down