Kotlin

null安全と例外処理

安全な呼び出し、早期return、require、try-catchを使って入力の失敗を扱います。

対象:Kotlin 2系・JDK 17以降のJVMコンソールアプリを対象にします。Android専用のAPIは使いません。

01

実行方法

入門の関数とnull安全までを使います。例ごとにMain.ktを全体ごと置き換えてIDEで実行します。ターミナルでは kotlinc Main.kt -include-runtime -d study.jar の後、java -jar study.jar を実行してください。

02

nullなら早めに戻る

?: return は左がnullのときに関数を終えます。次の例では戻り値を使って未登録を伝えます。早めに戻ると、正常な処理を深くネストせずに書けます。

Main.kt(全体を置き換え)KOTLIN
fun greeting(name: String?): String {
    val value = name?.trim() ?: return "名前がありません"
    if (value.isEmpty()) return "名前が空です"
    return "こんにちは、${value}さん"
}
fun main() {
    println(greeting(" Mity "))
    println(greeting(null))
    println(greeting(" "))
}
実行結果OUTPUT
こんにちは、Mityさん
名前がありません
名前が空です
03

letで値がある場合だけ処理

?.let { ... } はnullでない値を処理します。value -> に名前を付けると、何を使っているか読みやすくなります。nullではラムダ式を実行しません。

Main.kt(全体を置き換え)KOTLIN
fun main() {
    for (text in listOf("12", "abc")) {
        val number = text.toIntOrNull()
        number?.let { value -> println(value * 2) }
        if (number == null) println("変換できません")
    }
}
実行結果OUTPUT
24
変換できません
04

関数の前提条件を守る

require は条件を満たさない引数にIllegalArgumentExceptionを投げます。呼び出し元はtry-catchで受け取り、利用者へ説明します。

Main.kt(全体を置き換え)KOTLIN
fun total(price: Int, count: Int): Int {
    require(price >= 0) { "価格は0以上です" }
    require(count >= 1) { "個数は1以上です" }
    return price * count
}
fun main() {
    for (count in listOf(3, 0)) {
        try {
            println(total(120, count))
        } catch (error: IllegalArgumentException) {
            println(error.message)
        }
    }
}
実行結果OUTPUT
360
個数は1以上です

nullは値がないこと、例外は処理を通常どおり続けられないことを示します。空欄が許される項目はnull、数値の範囲違反などは検証結果として扱う、といったルールを決めましょう。

05

練習:年齢を検証

文字列から0〜130の年齢を取り出し、不正ならnullを返す関数を書きます。"20"、"abc"、"-1"で結果を確かめてください。

解答例と結果を確認する

まず自分で書いてから、処理の順番と結果を比べましょう。

Main.kt(全体を置き換え)KOTLIN
fun parseAge(text: String): Int? {
    val age = text.toIntOrNull() ?: return null
    if (age !in 0..130) return null
    return age
}
fun main() {
    for (text in listOf("20", "abc", "-1")) {
        val age = parseAge(text)
        println(age?.toString() ?: "年齢が不正です")
    }
}
実行結果OUTPUT
20
年齢が不正です
年齢が不正です

公式ドキュメントで確認する:null安全 / 例外