Kotlinの null安全(Null Safety) は、Javaなどで頻発してきたNullPointerException(NPE)を「実行時」ではなく「設計とコンパイル時」に防ぐ ための、言語設計の中核となる仕組みです。
単なる便利構文の集合ではなく、
「nullを許可するかどうかを型で明示し、危険な操作をコンパイル時に排除する」
という明確な思想に基づいています。
Kotlinでは「nullを型で制御する」
Kotlin最大の特徴は、nullを許容するかどうかを型として区別する点にあります。
非null型(デフォルト)
var name: String = "Kotlin"
// name = null // コンパイルエラー
Stringは nullを一切許容しない型- nullを代入しようとすると コンパイル時点でエラー
このため、純粋なKotlinコード内では「うっかりnullが入る」ことが起きません。
null許容型(Nullable Type)
var nickname: String? = "Kot"
nickname = null // OK
?を付けた型のみが null を保持できるStringとString?は 完全に別の型
Kotlinではこの区別が強制されるため、nullを扱う箇所がコード上で明確に可視化されます。
null許容型は「そのまま使えない」
val length = nickname.length // コンパイルエラー
nullの可能性がある値に対して、Kotlinは 直接のプロパティ・メソッドアクセスを許可しません。
これが「null安全」の第一の防波堤です。
セーフコール演算子 ?.
null許容型を安全に扱う基本が セーフコール演算子 です。
val length = nickname?.length
挙動
nickname == null→ 結果はnullnickname != null→lengthを返す- NPEは発生しない
重要な点として、結果の型は Int?(nullable)になる ことを理解しておく必要があります。
エルビス演算子 ?:(null時の代替処理)
nullableな結果に対して、nullだった場合の処理を明示するのがエルビス演算子です。
val length = nickname?.length ?: 0
- null →
0 - 非null → 実際の
length
?: の右側は単なる値だけでなく、式も書けます。
val name = nickname ?: error("nickname is required")
このため、「nullなら例外」「nullならreturn」などの制御フローにも頻繁に使われます。
非nullアサーション演算子 !!(最終手段)
val length = nickname!!.length
- 「ここは絶対にnullではない」と開発者が宣言する演算子
- nullだった場合は NPE系の例外が即発生
評価
- 安全性を放棄するため多用はNG
- Java移行コードや、明確な不変条件がある場合のみ限定使用
Kotlinで !! が頻出するコードは、設計段階でnullを適切に扱えていない可能性が高い と判断されます。
let による安全なスコープ処理
nullでない場合のみ処理を行いたいときに多用されるのが let です。
nickname?.let {
println(it.length)
println(it.uppercase())
}
特徴
- nullの場合はブロックが実行されない
itは 確実に非null- スコープを限定でき、変数汚染を防げる
UI更新、ログ出力、副作用処理との相性が非常に良い構文です。
スマートキャスト(Smart Cast)
Kotlinは nullチェック後に自動で型を絞り込む 機能を持っています。
if (nickname != null) {
println(nickname.length) // Stringとして扱われる
}
注意点(重要)
スマートキャストが成立するには条件があります。
- 対象が
val(不変) である - あるいは、コンパイラが「この変数は途中で変更されない」と証明できる場合
var やカスタムgetterが絡む場合、スマートキャストされないケースもあるため注意が必要です。
lateinit と null安全
lateinit var userName: String
特徴
- nullを許容しない
- 初期化を後回しにできる
varにしか使えない
注意点
println(userName) // 初期化前だと例外
UninitializedPropertyAccessExceptionが発生- null安全とは 別軸の仕組み
主にDI・Android・テスト用途で使われます。
Javaとの相互運用とプラットフォーム型
Java由来の値は、Kotlinでは プラットフォーム型(例:String!) になる場合があります。
val text = javaMethod() // String!
- nullかもしれないし、違うかもしれない
- Kotlinが安全性を保証できない型
補足(重要)
Java側に @Nullable / @NotNull などの
nullabilityアノテーションが付いている場合、
Kotlinは String? / String として推論できます。
つまり、Java連携は「常に危険」ではなく、設計次第で安全性を高められます。
KotlinでもNPEが起きる主なケース
Kotlinでも、以下のような「抜け道」では例外が発生します。
!!の使用- Java相互運用による想定外のnull
lateinitの未初期化アクセス- 明示的にNPEを投げた場合
ただし、純粋なKotlinコードだけで正しく設計すれば、NPEはほぼ排除できます。
実務でのベストプラクティス
- 非null型を基本に設計する
- nullは「仕様上必要な場合のみ許容」
!!は最後の手段?.+?:+letを適切に組み合わせる- Java連携部分は特に慎重に扱う
まとめ
Kotlinのnull安全は、
nullを「扱う技術」ではなく、「発生させない設計」
を実現するための仕組みです。
- nullを型で明示
- 危険な操作をコンパイル時に排除
- コード量とバグを同時に減らす
この考え方を正しく理解すると、Kotlinらしい、堅牢で読みやすいコード が自然に書けるようになります。
以上、Kotlinのnull安全についてでした。
最後までお読みいただき、ありがとうございました。










