はじめに
Kotlin には、他の言語にはあまり見られない特殊な型
Nothing という型があります。
名前の通り「何もない」ことを表しますが、
その実態は 「絶対に値を返さないことを示す型」 です。
1. Nothingとは何か?
Kotlin における Nothing は次のように定義されています:
Nothingは すべての型のサブタイプ(bottom type) であり、
絶対に値を返さない式を表すために使われます。
つまり:
- 戻り値を持たない関数(例外を投げる、無限ループなど)
- 到達不能なコード
- 「値が存在しない」ことを静的に示すとき
に登場します。
2. 代表的な例:例外を投げる関数
fun fail(message: String): Nothing {
throw IllegalStateException(message)
}
この関数は例外をスローして 絶対に戻らない ため、
戻り値型を Nothing として宣言できます。
呼び出し側ではこう使えます:
val name: String = fail("Name not found!") // ✅ コンパイルOK
fail() の型は Nothing ですが、
Nothing は どんな型にも代入可能 なため、
String にも代入できます(実行時は到達しません)。
3. throw式の型はNothing
throw 自体が Nothing 型の式です。
val x: Int = throw IllegalArgumentException()
このように、throw は「値を返さない」ことが明確なので、
右辺の型が Int に自動的に一致します。
4. when式での活用例
Nothing は when 式と非常に相性が良いです。
fun getColor(code: Int): String = when (code) {
1 -> "Red"
2 -> "Blue"
else -> throw IllegalArgumentException("Invalid code")
}
else の式は Nothing 型ですが、
全体として String 型の when 式が完成します。
→ throw が「値を返さない式」として扱われるため、
型の整合性を崩さず安全に例外を投げられる。
5. 永久ループにも使える
fun infiniteLoop(): Nothing {
while (true) {
println("Forever...")
}
}
この関数は決して終了しないので、
「戻り値を返さない関数」として Nothing を付けられます。
6. エラーハンドリング関数
標準ライブラリにも Nothing を返す関数がいくつかあります。
fun error(message: Any): Nothing = throw IllegalStateException(message.toString())
fun TODO(): Nothing = throw NotImplementedError()
つまり TODO() も実際には Nothing を返しています:
val data = TODO("Not yet implemented")
→ コンパイルOK(data の型は自動で推論される)
→ 実行時には NotImplementedError がスローされる。
7. Nothingは全ての型のサブタイプ
Kotlin の型階層の最下層に位置します:
Any
├── Any?
└── Nothing
-
Nothingは どんな型にも代入可能 - 逆に、どんな値も
Nothing型として扱うことは 不可能
つまり「存在しない値」を安全に表せる特殊な型です。
val x: String = throw Exception()
val n: Nothing = 123 // ❌ コンパイルエラー
図で見る型階層
Any
├── Unit (関数は戻る)
├── Int, String, ...
└── Nothing (関数は戻らない)
8. Nothing vs Unit vs Void の違い
| 型 | 意味 | 値を返す? | 戻る? | 代表例 |
|---|---|---|---|---|
Nothing |
絶対に値を返さない | ❌ | ❌ |
throw, fail(), TODO()
|
Unit |
値を返さない(void) | ✅ (Unit) |
✅ | println() |
Void |
Java の void 互換 | ❌ | ✅ | Java interop 用 |
9. 実践例:nullチェック関数
fun <T> checkNotNull(value: T?, message: String = "Value is null"): T {
return value ?: throw IllegalArgumentException(message)
}
ここでも throw の部分が Nothing 型なので、
全体は T 型として型安全に扱えます。
10. 応用:sealed class と組み合わせて安全分岐
Nothing は「あり得ない状態」を静的に表すこともできます。
sealed class Result<out T>
data class Success<T>(val value: T): Result<T>()
data class Failure(val error: Throwable): Result<Nothing>()
ここで Failure が Result<Nothing> を継承することで、
Success<T> と型的に両立できるようになります。
(Nothing はあらゆる型のサブタイプなので)
まとめ
| 項目 | 内容 |
|---|---|
| 型名 | Nothing |
| 意味 | 「絶対に値を返さない」型 |
| 特徴 | すべての型のサブタイプ(bottom type) |
| 主な用途 | 例外・終了・未実装・到達不能な分岐など |
| 関連 |
Unit, Void との比較で理解が深まる |
| 代表関数 |
throw, TODO(), error()
|
Kotlin の Nothing は
「到達不能コードを型安全に扱う」ための“最後の型” です。
これを理解すると、
「throw」「TODO」「return しない関数」の意味が
すべて 型の文脈で説明できるようになります。