Skip to content

null安全性

Kotlinでは、null値を持つことが可能です。Kotlinは、何かが欠けている場合やまだ設定されていない場合にnull値を使用します。 コレクションの章で、マップに存在しないキーを持つキーと値のペアにアクセスしようとしたときに、Kotlinがnull値を返す例をすでに見てきました。このようにnull値を使用することは便利ですが、コードがそれらを処理する準備ができていない場合、問題が発生する可能性があります。

プログラムでのnull値に関する問題を防止するために、Kotlinにはnull安全性(null safety)が導入されています。null安全性は、null値に関する潜在的な問題を、実行時ではなくコンパイル時に検出します。

null安全性は、以下のことを可能にする機能の組み合わせです。

  • プログラム内でnull値が許可される場合を明示的に宣言する。
  • null値をチェックする。
  • null値を含む可能性のあるプロパティや関数に対して安全な呼び出しを使用する。
  • null値が検出された場合に実行するアクションを宣言する。

ヌル許容型

Kotlinはヌル許容型(nullable types)をサポートしており、宣言された型がnull値を持つ可能性を許容します。デフォルトでは、型はnull値を受け入れることはできません。ヌル許容型は、型宣言の後に明示的に?を追加することによって宣言されます。

例:

kotlin
fun main() {
    // neverNull has String type
    var neverNull: String = "This can't be null"

    // Throws a compiler error
    neverNull = null

    // nullable has nullable String type
    var nullable: String? = "You can keep a null here"

    // This is OK
    nullable = null

    // By default, null values aren't accepted
    var inferredNonNull = "The compiler assumes non-nullable"

    // Throws a compiler error
    inferredNonNull = null

    // notNull doesn't accept null values
    fun strLength(notNull: String): Int {                 
        return notNull.length
    }

    println(strLength(neverNull)) // 18
    println(strLength(nullable))  // Throws a compiler error
}

TIP

lengthは、文字列内の文字数を含むStringクラスのプロパティです。

null値のチェック

条件式内でnull値の存在をチェックできます。次の例では、describeString()関数は、maybeStringnullなく、そのlengthがゼロよりも大きいかどうかをチェックするif文を持っています。

kotlin
fun describeString(maybeString: String?): String {
    if (maybeString != null && maybeString.length > 0) {
        return "String of length ${maybeString.length}"
    } else {
        return "Empty or null string"
    }
}

fun main() {
    val nullString: String? = null
    println(describeString(nullString))
    // Empty or null string
}

セーフコール(Safe calls)の使用

null値を含む可能性のあるオブジェクトのプロパティに安全にアクセスするには、セーフコール演算子(safe call operator)?.を使用します。セーフコール演算子は、オブジェクトまたはアクセスされたプロパティのいずれかがnullの場合にnullを返します。これは、null値の存在によってコード内でエラーがトリガーされるのを避けたい場合に役立ちます。

次の例では、lengthString()関数は、文字列の長さまたはnullを返すためにセーフコールを使用しています。

kotlin
fun lengthString(maybeString: String?): Int? = maybeString?.length

fun main() { 
    val nullString: String? = null
    println(lengthString(nullString))
    // null
}

TIP

セーフコールは連鎖させることができ、オブジェクトのいずれかのプロパティがnull値を含んでいる場合、エラーがスローされずにnullが返されます。例:

kotlin

  person.company?.address?.country

セーフコール演算子は、拡張関数やメンバー関数を安全に呼び出すためにも使用できます。この場合、関数が呼び出される前にnullチェックが実行されます。チェックがnull値を検出した場合、その呼び出しはスキップされ、nullが返されます。

次の例では、nullStringnullであるため、.uppercase()の呼び出しはスキップされ、nullが返されます。

kotlin
fun main() {
    val nullString: String? = null
    println(nullString?.uppercase())
    // null
}

エルビス演算子(Elvis operator)の使用

null値が検出された場合に返すデフォルト値を提供するには、エルビス演算子(Elvis operator)?:を使用します。

エルビス演算子の左側には、null値をチェックする対象を記述します。 エルビス演算子の右側には、null値が検出された場合に何を返すかを記述します。

次の例では、nullStringnullであるため、lengthプロパティにアクセスするためのセーフコールはnull値を返します。 その結果、エルビス演算子は0を返します。

kotlin
fun main() {
    val nullString: String? = null
    println(nullString?.length ?: 0)
    // 0
}

Kotlinのnull安全性に関する詳細については、Null safetyを参照してください。

練習

練習問題

会社の従業員のデータベースにアクセスできるemployeeById関数があります。残念ながら、この関数はEmployee?型の値を返すため、結果はnullになる可能性があります。あなたの目標は、従業員のidが提供されたときにその従業員の給与を返す関数、またはデータベースに従業員が存在しない場合は0を返す関数を作成することです。

|---|---|

kotlin
data class Employee (val name: String, var salary: Int)

fun employeeById(id: Int) = when(id) {
    1 -> Employee("Mary", 20)
    2 -> null
    3 -> Employee("John", 21)
    4 -> Employee("Ann", 23)
    else -> null
}

fun salaryById(id: Int) = // Write your code here

fun main() {
    println((1..5).sumOf { id -> salaryById(id) })
}

|---|---|

kotlin
data class Employee (val name: String, var salary: Int)

fun employeeById(id: Int) = when(id) {
    1 -> Employee("Mary", 20)
    2 -> null
    3 -> Employee("John", 21)
    4 -> Employee("Ann", 23)
    else -> null
}

fun salaryById(id: Int) = employeeById(id)?.salary ?: 0

fun main() {
    println((1..5).sumOf { id -> salaryById(id) })
}

次のステップ

おめでとうございます!初級ツアーを完了したところで、中級ツアーでKotlinの理解をさらに深めましょう:

中級Kotlinツアーを開始する