【Kotlin】スマートキャスト、エルビス演算子、Null安全【Androidアプリ開発】
Kotlinの基礎を学んだので、今回はNull安全についてまとめてみた。Javaでは、ぬるぽ (NullPointerException) が許されているが、Kotlinはぬるぽにならないような仕組みでできている。オブジェクトが、nullであり得るか否かを明確に区別する。
スマートキャスト
Nullableな変数を自動的にNotNullへキャストしてくれる。
val x:Int? = "3".toInt()
val y:Int? = "2".toInt()
if (x == null || y == null) {
return
}
println(x * y) // ここではx、yはNotNullとなっている
なんと、型に対してもスマートキャストは働く。 下のコードの if (obj !is String) return null に注目。
引数objはAny型で渡されたが、いつの間にかobj.lengthのようにStringクラスのメソッドが使える用になっている。これは if (obj !is String) return nullでのチェック以降は、自動的にStringクラスにキャストされたのだ。
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null // `!is` は `is`の否定形
return obj.length
}
もちろん、if文だけでなくwhen文でも使える。xの型によって処理を分けられるのだ。
when (x) {
is Int -> // xはInt型にキャストされている
is String -> // xはString型にキャストされている
is Hoge -> // xはHoge型にキャストされている
is Fuga -> // xはFuga型にキャストされている
else -> // xはその他の型にキャストされている
}
エルビス演算子
エルビス演算子 ?: を使えば、nullであった場合のデフォルト値を渡すことができる。 次のように使えるだろう。
val files = File("Hoge").listFiles()
println(files?.size ?: "ファイルが空です")
val email = "hoge@fuga.xxxxx"
println(email.firstOrNull() ?: "")
val values = mapOf<String, String?>("email" to null)
val email:String? = values["email"] ?: throw IllegalStateException("Email is missing!")
if (email != null) {
println(email)
}
上記の例外をスローさせたい場合に、エルビス演算子ではなく requireNotNull を使っても良い。
var fuga:String? = null
var hoge: String = requireNotNull(fuga, {
fuga = "fuga"
"${fuga} は nullなわけがない"
})
ここでは第二引数にラムダ式で、例外時のメッセージを渡すようになっている。
安全呼び出し
オブジェクトがnullでなかったら、メソッドを実行したい場合はあるだろう。たとえばデリゲートパターンだ。Swiftでは良くやるが、Kotlinでも同じように書くことができる。
public var delegate:Hoge? = null
...
delegate?.someMethod() // delegateがnull出ない場合のみ実行される。
関数letと組み合わせると、次の表現も可能だ。オブジェクトがnullでない場合、letに処理を任せる といったイメージだ。
val value = null
value?.let {
println("valueがnullでなければここが実行される")
}
let内のラムダ式では、itが使える。エルビス演算子と組み合わせれば、次のように簡潔な表現ができる。
val hoge:String? = "ほげほげ"
val fuga = hoge?.let { it + " ふがふが" } ?: ""
println(fuga) //=> ほげほげ ふがふが
Booleanだってnullableになりたい!
SwiftだとBoolはオプショナル型(nil)にはなれなかったはず。 Kotlinなら次のように、Boolean値がオプショナル型になることができる。
val b: Boolean? = true
if (b == true) {
println("b は true")
} else {
println("b は false か null である")
}
参考
Basic Syntax - Kotlin Programming Language Idioms - Kotlin Programming Language
▼ こんな記事も書いてます。