Kotlin M9で追加されたPlatform Typeの話
Kotlinマイルストーン9がリリースされた!
KotlinのNull-safetyは死んでしまったのかい?
— たろう (@ngsw_taro) 2014, 10月 16
これについて。
Javaのメソッドの戻り値の型がPlatform Typeって呼ばれる特殊な感じになったらしい。
今まではJavaのメソッドの戻り値の型は@NotNull
などで明示していない限り、すべてNullableとして扱われていた。
// Java public static Integer id(final Integer value) { return value; }
// M9より前 val a = id(5) // aの型はInt? println(a.plus(2)) // コンパイルエラー
M9では上記の変数a
の型がPlatform Typeとなってこうなる。
// M9 val a = id(5) // aの型はInt! println(a.plus(2)) // => 7
このコードはコンパイル可能で、実行時にもエラーは起こらない。
コンパイルがうまく行くのはa
がPlatform Typeとして扱われるからで、実行時にエラーが起こらないのはa
がnull
でないから。Platform TypeのInt
なのでa
はInt!
型となる、らしい。
では、null
の場合はどうなるのか。
val b = id(null) // bの型はInt! println(b.plus(2)) // ここで例外
先ほどの例と同様にコンパイルは通る。しかし実行するとb.plus(2)
の箇所で例外を投げる。
Exception in thread "main" java.lang.NullPointerException at sample.SamplePackage$Main$6051fa33.main(Main.kt:8) at sample.SamplePackage.main(Main.kt:1) ・・・
ぬるぽ怖い。なので型を明示する。
val b: Int? = id(null) // bの型はInt? println(b.plus(2)) // コンパイルエラー
型を明示することでPlatform Type(Int!
)を使わずにNullable(Int?
)として変数を扱えるようになる。
逆にNotNullを表明することもできる。
val a: Int = id(5) // aの型はInt println(a.plus(2)) // => 7
さらにnull
が返ってくるにも関わらずNotNull型として宣言できちゃう。
val b: Int = id(null) // ここでNullPointerException println(b.plus(2))
コンパイルは通る。b
はInt
型として扱われるのでb.plus(2)
も問題なくコンパイルされる。
しかし今回の場合b
はnull
なのでval b: Int = id(null)
のタイミングでNPEが投げられる。コンパイルして生成されたバイトコードを見るとNullチェックが差し込まれているのがわかる*1。
このPlatform TypeによりJavaコードの呼び出しが手軽になった。けれど簡単にNullPointerException
が起こるようになってしまったと思う。。*2