はじめに
Kotlin では インライン関数 (inline function) を使うことで、高階関数の呼び出しコストを削減し、非ローカルリターン も可能になります。
しかし、場合によっては「引数の一部だけインライン化したくない」ケースがあります。
そのときに使うのが noinline 修飾子 です。
1. 通常の inline 引数
inline 関数の引数に渡されたラムダは、呼び出し元に展開されます。
inline fun execute(action1: () -> Unit, action2: () -> Unit) {
action1()
action2()
}
fun main() {
execute(
{
println("inline action1")
return // ✅ 非ローカルリターン(main を抜ける)
},
{
println("inline action2")
}
)
println("End") // 実行されない
}
inline のラムダは呼び出し元に展開されるため、外側の関数から return できる のが特徴です。
2. noinline を付けた場合
noinline を付けると、その引数は インライン展開されず、関数オブジェクトとして扱われます。
inline fun execute(noinline action1: () -> Unit, noinline action2: () -> Unit) {
action1()
action2()
}
fun main() {
execute(
{
println("noinline action1")
// return // ❌ 非ローカルリターンはできない
},
{
println("inline action2")
}
)
println("End") // 実行される
}
ポイント
-
action2はインライン化されない -
returnは 外側の関数に影響しない(通常のラムダと同じ) - 関数オブジェクトとして保持できるため、変数に格納したり、スレッド処理に渡すことが可能
3. noinline の使いどころ
-
ラムダを保持して後で実行したいとき
- コールバック関数、イベントリスナーなど
-
他の関数やスレッドに渡したいとき
-
Runnableや API に引数として渡す場合
-
-
非ローカルリターンを禁止したいとき
- 意図せず外側の処理が終了しないように制御する場合
4. inline / noinline / crossinline の違い
| 修飾子 | インライン化 | 非ローカルリターン | 関数オブジェクトとして保持 |
|---|---|---|---|
inline |
✅ 展開される | ✅ 可能 | ❌ 不可 |
noinline |
❌ 展開されない | ❌ 不可 | ✅ 可 |
crossinline |
✅ 展開される | ❌ 禁止 | ❌ 不可 |
まとめ
-
inlineで高階関数を効率化できる -
noinlineを付けると、そのラムダは インライン化されず、関数オブジェクトとして扱える - これにより 保持・遅延実行・別スレッド渡し が可能になる
-
inline/noinline/crossinlineを使い分けることで、安全かつ柔軟な高階関数を設計できる