Null Safetyって何?
Null Safety = 変数がNullの場合に安全に処理を行ってくれる
もう少し端的に述べるとNullPointerExceptionを防いでくれる。
Java経験がある方なら一度は経験したことのあるNullPointerException。
nullのメンバにアクセスしようとする際にNullPointerExceptionが生じ、アプリをクラッシュさせてしまう。
Null Safetyはこの事象を防ぐことを目的としている。
Non-NullとNullable
kotlinの変数の型にはNon-NullとNullableの2種類が存在する。
- Non-Null:null代入されない想定の型(null非許容)
- Nullable:nullが代入される想定の型(null許容)
上記のように、簡単に述べるとnullが代入できるかできないかの違いとなる。
実際にコードに記述する際はどうなるのか?
class MainActivity: AppCompatActivity() {
//kotlinでnullを非許容するとする型宣言(Non-Null)
var non_null_text: String = ""
//kotlinでnullを許容する型宣言(Nullable)
var nullable_text: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//コンパイルエラー
non_null_text = null
//nullが代入される
nullable_text = null
}
}
一般的なkotlinの型宣言はnon_null_text
のような形になると思うが、これだとnullは許容してくれない。
そのため、nullable_text
のように型名の後に?
をつけて宣言を行うことでnullを許容してくれるようになる。
Safe Callsと!! Operator
nullが入ってもいいようにString?
で型宣言も行い、試しにnullable_text.length
でも実行してみようと思ったが、エラーが生じてしまった。
エラー内容はonly safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
となっている。
冒頭でも述べたが、これはnullのメンバにアクセスすることでNullPointerExceptionが生じてしまうことを示している。
エラーの解決策としては、内容にも書かれているように?.
か!!.
をつければいい。
ただし、この2つは意味合いはまったく異なるものであることは理解しておいて欲しい。
コードの記述方法は2つとも似ている。
val length1 = nullable_text?.length
val length2 = nullable_text!!.length
上記の記述でコンパイルエラーはなくなる。
nullable_textがnullだった場合に、2つがどのような挙動をするのかというと、length1
では処理が通るが、length2
ではNullPointerExceptionが生じ、クラッシュしてしまう。
?.(Safe calls)
?.
を使用すると、もし変数がnullでなければそのまま処理を行うが、変数がnullの場合は処理を行わずにnullを返すようになる。
そのため、アプリがクラッシュするようなことはなくなる。
!!.(!! Operator)
!!.
を使用すると、もし変数がnullでなければそのまま処理を行うが、変数がnullの場合はNullPointerExceptionを返すようになる。
そのため、アプリがクラッシュする。
上記のような違いがあるので、使い分けは慎重に、特に!!.
は気をつけて使用する必要がありそう。
エルビス演算子
?.
を用いてnullable_text?.length
が使用できるようになったが、nullable_text
がnullの時は空文字を代入したい...
そのような時に役立つのがエルビス演算子?:
になる。
//nullable_textがnullの場合、length1にはnullが代入されてしまう
val length1 = nullable_text?.length
//nullable_textがnullの場合、length2には""(空文字)が代入される
val length2 = nullable_text?.length ?: "
エルビス演算子は、?:
より左側の処理がnullでないのであればそのまま処理を行い、nullであるのならば?:
より右側の処理を行う。
ただし、?:
より右側の処理が行われるのは?:
より左側がnullの時のみである。