この問題の歴史:
Elvis演算子(?:)はKotlinでnullable値を処理するための簡潔で安全な方法として登場しました。その名前は、側面から見るとエルビス・プレスリーの髪型に似ていることに由来しています。目的は、if (a != null) a else bのようなテンプレートコードを排除し、日常の開発をより便利にすることです。
問題:
nullになる可能性のある値に直接アクセスすると、実行時エラー(NullPointerException)が発生します。したがって、変数がnullの場合にデフォルト値を優雅に挿入できるツールが必要です。
解決策:
Elvis演算子はnullableタイプに適用されます。演算子の左側の式がnullでない場合、それが返され、そうでない場合は右側の式が返されます。これにより、コードがよりコンパクトで安全になります。
コードの例:
fun getLength(str: String?): Int { return str?.length ?: 0 } val result = getLength(null) // result == 0 val result2 = getLength("Hello") // result2 == 5
主な特徴:
Elvis演算子の右側に副作用のある式がある場合、常に実行されるのか?
いいえ!右側の式は左側がnullの場合にのみ計算されます。これは、関数が副作用を持つ場合や「コストのかかる」計算を行う場合に重要な役割を果たすことがあります。
コードの例:
var called = false val x: String? = "test" val y = x ?: run { called = true; "default" } // calledはfalseになる。なぜなら、runは実行されないから。
例外をスローするためにElvis演算子を使用することはできるのか?
はい、Kotlinでは次のように書くことができます:
fun getLengthStrict(str: String?): Int = str?.length ?: throw IllegalArgumentException("str is null")
もしstrがnullであれば、例外がスローされます。これはデータ検証の便利なメカニズムです。
複数のElvis演算子を連続して「つなげる」ことはできるのか?
はい、これはフォールバックの一般的なアプローチです:
val name = fromDatabase ?: fromCache ?: "Unknown"
この式は最初の非null値または文字列「Unknown」を返します。
Elvisを使った多層ネストのnullチェック:
val title = a?.b?.c?.d?.e ?: defaultTitle
長所:
短所:
ステップごとの明示的な分解、わかりやすい変数名:
val deepValue = a?.b val deeperValue = deepValue?.c?.d ?: default
長所:
短所: