Page History

nullの扱い

yhornisse edited this page on 20 Jun 2023

Clone this wiki locally

nullの扱い

KotlinはJavaに比べるとnullの扱いが特徴的である。 Javaのオブジェクト型の変数は基本的に全てNullableであるが、 Kotlinの場合は明示的に?を指定しない限りはnullを格納することができない。 例えばKotlinのそれぞれの型はJavaでは以下のような記載となる。

種別 Kotlin Java
非null var:String s @NotNull String s;
nullable var:String? s @Nullable String s;

非nullの変数にnullを格納することはできず、例えば以下のようなコードはビルド時にコンパイルエラーとなる。

  • コンパイルNG
    fun main(args: Array<String>) {
      val i:Int = null;
      println(i);
    }
  • コンパイルOK
    fun main(args: Array<String>) {
      val i:Int? = null;
      println(i);
    }

非null型の場合、当然だがNPEを回避するようなコードは不要である。 以上のようにJavaの場合はアノテーションを付けることで静的解析を行うが(あるいは人間がただ頑張るか)、 Kotlinの場合は言語レベルでケアする。

Nullable型を扱う場合は ?. や ?: の演算子を使用する。

val b:String? = "hello"
println(b?.length ?: -1) // 5

val a:String? = null
println(a?.length ?: -1) // -1

Nonnull ⇔ Nullable

Nonnnull型 → Nullable型への代入

Nonnull型からNullable型への変換はあまり気にする必要がない。

val v:Int = 1
val i:Int? = v

Nullable型 → Nonnull型への代入

Nullable型からNonnull型への代入はひと手間必要である。

  • コンパイルNG
    fun main(args: Array<String>) {
      val v:Int? = 1
      val i:Int = v
    }
  • コンパイルOK
    fun main(args: Array<String>) {
      val v:Int? = 1
      val i:Int = v!!
    }
  • コンパイルOKだが、実行時にぬるぽ
    fun main(args: Array<String>) {
      val v:Int? = null
      val i:Int = v!!
    }
  • コンパイルOK
    fun main(args: Array<String>) {
      val v:Int? = 1
      val i:Int = v ?: 0
    }

関数呼び出し

Nonnull型の関数呼び出しはぬるぽが起きることはないが、Nullableの場合は気にする必要がある。 Nullable の関数呼び出しの場合、 ?. (safe call) の演算子を使用する。

val i:Int? = null
i?.let { println(it) } // 実行されない

キャスト

  • (普通の)キャスト。型変換できない場合は例外がスロー。
    val v: Int? = a as Int
  • セーフキャスト 。型変換できない場合はnull
    val v: Int? = a as? Int

コレクション

val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()

tips

?.がnullの場合にletを処理せずにnullを返すため、?: nullの場合を処理を記載できる。

>>> var v:String? = null
>>> var s:String = v?.let { it.toUpperCase() } ?: ""
>>> println(s)

>>> var v:String? = "hoge"
>>> var s:String = v?.let { it.toUpperCase() } ?: ""
>>> println(s)
HOGE
>>>