Skip to content

戻りとジャンプ

Kotlinには、3つの構造化されたジャンプ式があります。

  • returnは、デフォルトでは最も近い囲み関数または匿名関数から戻ります。
  • breakは、最も近い囲みループを終了します。
  • continueは、最も近い囲みループの次のステップに進みます。

これらの式はすべて、より大きな式の一部として使用できます。

kotlin
val s = person.name ?: return

これらの式の型はNothing型です。

ラベル付きbreakとcontinue

Kotlinのあらゆる式には、ラベルを付けることができます。 ラベルは、abc@fooBar@のように、識別子の後に@記号が続く形式を持ちます。 式にラベルを付けるには、その式の前にラベルを追加するだけです。

kotlin
loop@ for (i in 1..100) {
    // ...
}

これで、breakまたはcontinueをラベルで修飾できます。

kotlin
loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (...) break@loop
    }
}

ラベルで修飾されたbreakは、そのラベルが付けられたループの直後の実行ポイントにジャンプします。 continueは、そのループの次のイテレーションに進みます。

場合によっては、明示的にラベルを定義することなく、breakcontinue非ローカルに適用できます。 このような非ローカルな使用法は、囲みインライン関数内で使用されるラムダ式で有効です。

ラベル付きreturn

Kotlinでは、関数リテラル、ローカル関数、オブジェクト式を使用して関数をネストできます。 修飾されたreturnを使用すると、外側の関数から戻ることができます。

最も重要なユースケースは、ラムダ式からの戻りです。ラムダ式から戻るには、 それにラベルを付け、returnを修飾します。

kotlin
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // ラムダの呼び出し元(forEachループ)へのローカルリターン
        print(it)
    }
    print(" done with explicit label")
}

fun main() {
    foo()
}

これで、ラムダ式からのみ戻ります。多くの場合、_暗黙的なラベル_を使用する方が便利です。なぜなら、そのようなラベルは、ラムダが渡される関数と同じ名前を持つためです。

kotlin
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach // ラムダの呼び出し元(forEachループ)へのローカルリターン
        print(it)
    }
    print(" done with implicit label")
}
//end

fun main() {
    foo()
}

あるいは、ラムダ式を匿名関数に置き換えることもできます。 匿名関数内のreturn文は、その匿名関数自体から戻ります。

kotlin
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
        if (value == 3) return  // 匿名関数の呼び出し元(forEachループ)へのローカルリターン
        print(value)
    })
    print(" done with anonymous function")
}

fun main() {
    foo()
}

前の3つの例におけるローカルリターンの使用は、通常のループにおけるcontinueの使用に似ていることに注意してください。

breakに直接相当するものはありませんが、外側のrunラムダを追加し、そこから非ローカルに戻ることでシミュレートできます。

kotlin
fun foo() {
    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop // runに渡されたラムダからの非ローカルリターン
            print(it)
        }
    }
    print(" done with nested loop")
}

fun main() {
    foo()
}

ここでの非ローカルリターンは、ネストされたforEach()ラムダがインライン関数として機能するため可能です。

値を戻す際、パーサーは修飾されたreturnを優先します。

kotlin
return@a 1

これは、「ラベル@a1を戻す」という意味であり、「ラベル付けされた式(@a 1)を戻す」という意味ではありません。

場合によっては、ラベルを使用せずにラムダ式から戻ることができます。このような非ローカルな戻りは、ラムダ内にありますが、囲みインライン関数を終了します。