Kotlin
Nullセーフティ
サーチ…
Null可能な型とNullableでない型
String
ような通常の型はnull可能ではありません。それらにヌル値を保持できるようにするには、 ?
それらの背後にある: String?
var string : String = "Hello World!" var nullableString: String? = null string = nullableString // Compiler error: Can't assign nullable to non-nullable type. nullableString = string // This will work however!
セーフコールオペレータ
null可能な型の関数とプロパティにアクセスするには、特別な演算子を使用する必要があります。
最初のもの、 ?.
アクセスしようとしているプロパティまたは関数を返します。オブジェクトがnullの場合はnullを返します。
val string: String? = "Hello World!" print(string.length) // Compile error: Can't directly access property of nullable type. print(string?.length) // Will print the string's length, or "null" if the string is null.
イディオム:ヌルチェックされた同じオブジェクト上で複数のメソッドを呼び出す
ヌルチェックされたオブジェクトの複数のメソッドを呼び出すエレガントな方法は、Kotlinのapply
ように使用していapply
:
obj?.apply {
foo()
bar()
}
これは、呼び出しますfoo
とbar
上obj
(あるthis
にapply
場合にのみブロック) obj
そうでない場合はブロック全体をスキップし、非nullです。
関数とプロパティの呼び出しの暗黙の受信者にすることなく、ヌル可能な変数をnullableでない参照としてスコープに入れるには、 apply
代わりにlet
を使うことができapply
:
nullable?.let { notnull ->
notnull.foo()
notnull.bar()
}
notnull
自由に名前を付ける、あるいは取り残さとを介して使用することができ、暗黙のラムダパラメータit
。
スマートキャスト
ある時点でオブジェクトがnullにならないとコンパイラが推論できる場合は、特別な演算子をもう使用する必要はありません。
var string: String? = "Hello!"
print(string.length) // Compile error
if(string != null) {
// The compiler now knows that string can't be null
print(string.length) // It works now!
}
注意:コンパイラは、nullチェックと意図された使用の間で変更される可能性があるスマートキャストの可変変数を許可しません。
変数が現在のブロックのスコープ外からアクセスできる場合(たとえば、非ローカルオブジェクトのメンバーなので)、スマートキャストして使用できる新しいローカル参照を作成する必要があります。
Iterableと配列からのヌルを排除する
時には型をCollection<T?>
からCollections<T>
に変更する必要があります。その場合、 filterNotNull
が私たちのソリューションです。
val a: List<Int?> = listOf(1, 2, 3, null)
val b: List<Int> = a.filterNotNull()
Null Coalescing / Elvis Operator
null可能な式をif-elseの方法で評価することが望ましいことがあります。エルツ演算子、 ?:
、このような状況のためにKotlinで使用できます。
例えば:
val value: String = data?.first() ?: "Nothing here."
戻って上記の式"Nothing here"
場合data?.first()
やdata
そのものが得null
他の値の結果data?.first()
同じ構文を使用して例外をスローして、コードの実行を中止することもできます。
val value: String = data?.second()
?: throw IllegalArgumentException("Value can't be null!")
注意: アサーション演算子を使用してNullPointerExceptionをスローすることができます(例:
data!!.second()!!
)
アサーション
!!
接尾辞はNULL値を無視し、その型のnull以外のバージョンを返します。オブジェクトがnull
場合、 KotlinNullPointerException
がスローされnull
。
val message: String? = null
println(message!!) //KotlinNullPointerException thrown, app crashes
エルビスオペレーター(?:)
Kotlinでは、 null reference
を保持できる変数を宣言できnull reference
。 null可能な参照a
があるとします。「 a
がnullでない場合はそれを使用し、そうでない場合はnull以外の値x
使用する」と言うことができます
var a: String? = "Nullable String Value"
さて、 a
はnullでもかまいません。したがって、 a
値にアクセスする必要がある場合、値が含まれているかどうかに関わらず、安全性チェックを実行する必要があります。この安全性チェックは、従来のif...else
ステートメントで実行できます。
val b: Int = if (a != null) a.length else -1
しかし、ここでは先行オペレータElvis
(演算子エルビス: ?:
:)が来る。上記のif...else
はElvis演算子で次のように表すことができます。
val b = a?.length ?: -1
?:
ここではa?.length
)の左側の式がnullでないa?.length
、elvis演算子はそれを返します。そうでない場合は、式を右側(ここでは-1
)に返します。右辺の式は、左辺がnullの場合にのみ評価されます。