!! 非nullアサーション
| 対応: | Kotlin 1.0(2016) |
|---|
Kotlinの『!!』(非nullアサーション演算子)は、Nullable型の値をnon-null型として扱う演算子です。値がnullの場合は『NullPointerException』がスローされます。
構文
// !! 演算子で Nullable 型を non-null 型に変換する val name: String? = "item_x" val length: Int = name!!.length // String? → String として扱う // null の場合は NullPointerException がスローされる val nullValue: String? = null val len = nullValue!!.length // 例外スロー
構文一覧
| 構文 | 概要 |
|---|---|
| value!! | null でなければ non-null 型として返します。null なら NullPointerException をスローします。 |
| value!!.method() | null チェックなしでメソッドを呼び出します。null なら例外がスローされます。 |
| value!!.property | null チェックなしでプロパティにアクセスします。 |
サンプルコード
sample_non_null_assertion.kt
// !! 演算子のデモ
fun getUser(id: Int): String? = if (id > 0) "User-$id" else null
fun main() {
// null でない場合は正常に動作する
val name: String? = "item_x"
println(name!!.length) // 6
println(name!!.uppercase()) // ITEM_X
// スマートキャストが使えない外部関数の結果に使う例
val user = getUser(1)!! // null でないことが分かっている場合
println("ユーザー: $user") // ユーザー: User-1
// !! を使わない安全な代替手法との比較
val nullable: String? = "Kotlin"
// 方法1: !! (nullなら例外)
println(nullable!!.length) // 6
// 方法2: ?.let(安全)
nullable?.let { println(it.length) } // 6
// 方法3: ?: (nullなら代替値)
println(nullable?.length ?: 0) // 6
// null の場合に !! を使うと例外が発生する
try {
val nullStr: String? = null
println(nullStr!!.length) // ここで例外
} catch (e: NullPointerException) {
println("例外キャッチ: ${e::class.simpleName}") // NullPointerException
}
}
コンパイルして実行すると次のようになります。
kotlinc sample_non_null_assertion.kt -include-runtime -d sample_non_null_assertion.jar java -jar sample_non_null_assertion.jar 6 ITEM_X ユーザー: User-1 6 6 6 例外キャッチ: NullPointerException
よくあるミス
sample_non_null_assertion_mistakes.kt
fun getUserName(id: Int): String? = if (id > 0) "item_x" else null
fun main() {
// null になりうる値に !! を使う
val name: String? = null
println(name!!.length) // NullPointerException がスローされる
// !! を連鎖させる
val user: String? = getUserName(-1)
println(user!!.trim()!!.uppercase()) // 2 箇所で NullPointerException の危険がある
// !! でキャッチしたつもりが例外型を間違える
try {
val nullStr: String? = null
println(nullStr!!.length)
} catch (e: KotlinNullPointerException) { // Kotlin 1.4 以降は NullPointerException
println("キャッチできない")
}
}
コンパイルして実行すると次のようになります。
kotlinc sample_non_null_assertion_mistakes.kt -include-runtime -d sample_non_null_assertion_mistakes.jar java -jar sample_non_null_assertion_mistakes.jar Exception in thread "main" java.lang.NullPointerException
概要
『!!』演算子はKotlinのNull安全機能をバイパスするため、null以外であることが確実な場面で使われます。プロダクションコードでは『?.』演算子や『?:』エルビス演算子、『?.let』による安全な代替手法と使い分ける傾向があります。
注意: nullが入る可能性がある箇所で『!!』を使うと NullPointerException が発生します。代わりに『?.』演算子や『?:』エルビス演算子、『?.let』を検討してください。
Nullable型の基本はNullable 型 / ?. 演算子を、デフォルト値の設定には?: エルビス演算子を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。