B-Teck!

お仕事からゲームまで幅広く

【Kotlin】KotlinのNull安全

dogwood008.github.io KotlinのリファレンスのNull安全のページが英語しかなさそうだったので、ざっくり翻訳しつつ例を足したりした。

Null安全

Kotlinでは下記の要因以外でNPEを起こすことが無いよう作られている。

  • 明示的な throw NullPointerException()
  • !! 演算子を使用した場合
  • 外部のJavaコードが原因の場合
  • コンストラクタで利用可能な初期化されていないthisが使用されている

Null可能値

Null値を取りうる変数は明示的にNull可能値としなければならない

var a: String = "abc"
a = null // コンパイルエラー
val l = a.length

var b: String? = "abc"
b = null // ok
val l = b.length // bはNullableなのでエラー

Non-Nullableなオブジェクトは安全にプロパティにアクセスできる。
NullableなオブジェクトはNPEの可能性があるためエラーとなる。

Nullableなオブジェクトにアクセスしたい場合

Nullチェックを行う

val a :String? = "testa"
var b :String? = "testb"
var c :String? = "testc"

val l = if (a != null) print("String of length ${a.length}\n") else print("\n")

if (b != null && b.length > 0)
    print("String of length ${b.length}\n")
else
    print("Empty string\n")

if (c != null && c.length > 0){
    c = null // nullを代入できてしまう!
    print("String of length ${c.length}\n")
}else{
    print("Empty string\n")
}

Nullチェックを行った後は、Nullableなオブジェクトが自動でキャストされ、
プロパティにアクセスが可能になる。
varの場合、チェック後にnullを代入出来てしまうため注意

安全呼び出し

val l:Int? = b?.length

上記の場合、bがnullならnullを、そうでなければb.lengthlに代入する。
Intまたはnullが返却されるため型はInt?となる

bob?.department?.head?.name

安全呼び出しはチェーンすることができ、上記の場合はいずれかのプロパティがnullならnullを返す。

その他のNullに関する演算子等

エルビス演算子

val l: Int = b?.length ?: -1

上記の場合,b?.lengthがnullでない場合はb.length、nullの場合は右辺が評価されて-1を返す。

!!演算子

val l = b!!.length()

上記の場合、b.length()がnullであればNPEを発生させる。 nullでない場合はエルビス演算子と同様にb.lengthの値を返す。

セーフキャスト

val aInt: Int? = a as? Int

上記の例ではaがnullの場合はaIntはnull、nullでない場合はaとなる。
KotlinのキャストはNull安全でないため、正しい型でないとClassCastExceptionが発生してしまう。
セーフキャストを行う事でエラーを避けて安全なキャストができる。