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
値を受け入れることはできません。ヌル許容型は、型宣言の後に明示的に?
を追加することによって宣言されます。
例:
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()
関数は、maybeString
がnull
でなく、そのlength
がゼロよりも大きいかどうかをチェックするif
文を持っています。
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
を返すためにセーフコールを使用しています。
fun lengthString(maybeString: String?): Int? = maybeString?.length
fun main() {
val nullString: String? = null
println(lengthString(nullString))
// null
}
TIP
セーフコールは連鎖させることができ、オブジェクトのいずれかのプロパティがnull
値を含んでいる場合、エラーがスローされずにnull
が返されます。例:
person.company?.address?.country
セーフコール演算子は、拡張関数やメンバー関数を安全に呼び出すためにも使用できます。この場合、関数が呼び出される前にnullチェックが実行されます。チェックがnull
値を検出した場合、その呼び出しはスキップされ、null
が返されます。
次の例では、nullString
がnull
であるため、.uppercase()
の呼び出しはスキップされ、null
が返されます。
fun main() {
val nullString: String? = null
println(nullString?.uppercase())
// null
}
エルビス演算子(Elvis operator)の使用
null
値が検出された場合に返すデフォルト値を提供するには、エルビス演算子(Elvis operator)?:
を使用します。
エルビス演算子の左側には、null
値をチェックする対象を記述します。 エルビス演算子の右側には、null
値が検出された場合に何を返すかを記述します。
次の例では、nullString
がnull
であるため、length
プロパティにアクセスするためのセーフコールはnull
値を返します。 その結果、エルビス演算子は0
を返します。
fun main() {
val nullString: String? = null
println(nullString?.length ?: 0)
// 0
}
Kotlinのnull安全性に関する詳細については、Null safetyを参照してください。
練習
練習問題
会社の従業員のデータベースにアクセスできるemployeeById
関数があります。残念ながら、この関数はEmployee?
型の値を返すため、結果はnull
になる可能性があります。あなたの目標は、従業員のid
が提供されたときにその従業員の給与を返す関数、またはデータベースに従業員が存在しない場合は0
を返す関数を作成することです。
|---|---|
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) })
}
|---|---|
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の理解をさらに深めましょう: