Kotlinのダブルバン(!!)演算子とは?使い方とNullPointerExceptionの挙動を解説
Kotlinにおける「!!」は、ダブルバン(double-bang)演算子と呼ばれる演算子です。別名「非NULL表明演算子(not-null assertion operator)」とも呼ばれます。この演算子は、任意の値を非NULL型の値へと変換するために使用され、対象の値がNULLであった場合には例外(NullPointerException)をスローします。
KotlinはNULL安全(null safety)を重視した言語であり、通常はコンパイル段階でNULL参照のリスクを排除できます。しかし、「この値は絶対にNULLではない」と開発者が明示的に保証したい場面もあります。そんなときに活躍するのが「!!」演算子です。
例1:通常のNULL許容型の扱い
ここでは、変数「name」を用意し、プログラマーとして「name」の値がNULLである場合にNullPointerExceptionをスローしたいという要件を考えます。まずは、次のコードを実行してみましょう。
fun main(args: Array<String>) {
var name: String?
name = null
println(name)
}出力結果
上記のコードを実行すると、次の出力が得られます。
null
このコードは、残念ながら私たちの要件を満たしていません。「name」の値がNULLの場合にNullPointerExceptionをスローしたいのに、実際には単に「null」と出力されるだけだからです。そこで、ダブルバン演算子(!!)を使って先ほどのコードを修正してみましょう。
例2:ダブルバン演算子(!!)を使用した場合
fun main(args: Array<String>) {
var name: String?
name = null
// オーバーロードの曖昧性による例外を解決するためNothing?を使用
println(name!! is Nothing?)
}出力結果
今度は、実行時にNullPointerExceptionがスローされます。
Exception in thread "main" java.lang.NullPointerException
at MainKt.main(main.kt:6)
これは、「name」に「!!」を適用した時点で値がNULLであることが検出され、例外が発生したためです。つまり、ダブルバン演算子は「値がNULLでないこと」を強制的に主張し、もしNULLであれば即座に実行時例外を引き起こす働きを持っています。
ダブルバン演算子使用時の注意点
「!!」は手軽な一方で、安易に使用すると実行時例外の原因となり、アプリケーションのクラッシュにつながる可能性があります。実務では、以下のようなNULL安全な代替手段の利用も検討しましょう。
- セーフコール演算子(?.):値がNULLの場合に例外ではなく「null」を返します。
- エルビス演算子(?:):値がNULLの場合に代わりのデフォルト値を返します。
- let関数:値がNULLでない場合にのみ処理を実行します。
「!!」の使用は、テストコードや「論理的にNULLになり得ないことが明確な場面」など、限定的な状況にとどめることが推奨されます。
-
「マイ・ネーム・イズ・ジェフ」ミームとは?映画『22ジャンプストリート』発の名言の由来と拡散の歴史
2017年初頭にサービスを終了した短尺動画アプリVine(ヴァイン)をよく見ていた人なら、「My name is Jeff(私の名前はジェフ)」というミームを覚えているかもしれません。映画『22ジャンプストリート』のこの有名なセリフは、今でもTikTokをはじめとする各プラットフォームでたびたび登場する人気ネタです。「マイ・ネーム・イズ・ジェフ」ミームの起源「My name is Jeff」というセリフが生まれたのは、映画『22ジャンプストリート』のワンシーンです。チャニング・テイタム演じるキャラクターが外国語のアクセントを真似ようとするものの、見事に失敗してしまう——それが爆笑必至の名場面と
-
C#の演算子の優先順位とは?基本ルールとサンプルコードで解説
演算子とは演算子(オペレーター)とは、コンパイラに対して特定の数学的処理や論理処理を実行するよう指示するための記号です。C#には、算術演算子・関係演算子・論理演算子など、さまざまな種類の演算子が用意されています。演算子の優先順位とは演算子の優先順位とは、1つの式の中で各項がどのようにグループ化され、どの順番で評価されるかを決めるルールです。この優先順位は式の評価結果に直接影響します。すべての演算子が同じ優先順位を持つわけではなく、たとえば乗算演算子(*)は加算演算子(+)よりも高い優先順位を持ちます。そのため、a + b * c という式は (a + b) * c ではなく a + (b *