LoginSignup
21
15

More than 3 years have passed since last update.

KotlinのNull Safety攻略ガイド

Last updated at Posted at 2019-09-21

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の時のみである。

21
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
15