Kotlinにおける var と val の違いは、単なる文法上の話ではありません。
コードの安全性・可読性・設計思想に直結する重要な概念です。
ここでは、よくある誤解を避けつつ、Kotlinの仕様に忠実な形で詳しく解説します。
基本的な違い
まず最も基本となる違いです。
| キーワード | 再代入 | 意味 |
|---|---|---|
var | 可能 | 再代入できる変数 |
val | 不可 | 再代入できない変数(setterがない) |
var a = 10
a = 20 // OK
val b = 10
b = 20 // コンパイルエラー
この点だけを見ると、val は「一度決めたら変えられない変数」と理解して問題ありません。
val は「定数」ではない
Kotlinで最も誤解されやすいポイントです。
よくある誤解
valは定数(immutable)
正しい理解
valは 再代入できないだけ であり、
参照先オブジェクトの状態が不変とは限らない
val list = mutableListOf(1, 2, 3)
list.add(4) // 問題なく動く
listという 参照そのものは変更不可listが指している オブジェクトの中身は変更可能
つまり、
val= read-only(参照の再代入不可)- immutable(完全不変)とは別概念
ローカル変数の val と プロパティの val は少し意味が違う
ローカル変数(関数内)
fun sample() {
val x = 10
// x = 20 は不可
}
この場合の val は非常に単純で、
- 一度代入したら終わり
- Javaの
finalローカル変数とほぼ同じ感覚
と考えて問題ありません。
クラスのプロパティ
class Sample {
val value = 10
}
プロパティの val は、より正確には次の意味になります。
setter(代入手段)が存在しないプロパティ
ここで重要なのは、getterは自由に定義できる という点です。
class Sample {
val now: Long
get() = System.currentTimeMillis()
}
この場合、
valであるにも関わらず- アクセスするたびに値が変わる
という挙動になります。
重要な結論
valは「再代入不可」を保証する- 「常に同じ値を返す」ことまでは保証しない
var の本質
var は「状態が変化することを許可する」変数です。
var status = "INIT"
status = "LOADING"
status = "DONE"
特徴
- 値の変化を追う必要がある
- ロジックが複雑になるほど可読性が下がる
- バグが入り込みやすい
そのため Kotlin では、明確に必要な場合にのみ var を使う のが一般的です。
Kotlinで val が好まれる理由
Kotlinは言語設計として「不必要な変更を防ぐ」方向に寄っています。
val を使うメリット
コードの意味が固定される
val total = price * quantity
「この値は途中で変わらない」と即座に理解できる。
バグを防ぎやすい
- 意図しない再代入が起こらない
- 修正箇所が限定される
可読性が高い
- 状態変化を追う必要がない
- 認知負荷が低い
並行処理との関係
よくある言い回しとして「val はスレッドセーフ」と言われることがありますが、これは正確ではありません。
正確な整理
valは「再代入」を防ぐだけ- 参照先がミュータブルなら普通に壊れる
val list = mutableListOf<Int>()
// 複数スレッドから add すれば問題は起きる
正しい言い方
valは 競合の原因を減らす助けにはなる- しかし スレッド安全性を保証するものではない
クラス設計での使い分け
不変なデータモデル
data class User(
val id: Int,
val name: String
)
- 状態が固定される
- 安全で扱いやすい
状態が変わるモデル
class User(
var name: String
)
- UI状態
- 編集途中の値
- 明確に「変わる」ことが前提のデータ
val と const val の違い
val x = 10
const val Y = 10
| 項目 | val | const val |
|---|---|---|
| 再代入 | 不可 | 不可 |
| コンパイル時定数 | × | ○ |
| 宣言場所 | どこでも | トップレベル / object / companion object |
| 型 | 任意 | プリミティブ・String など限定 |
const val は 本当の意味での定数 です。
Javaとの対応関係
| Kotlin | Java |
|---|---|
val(ローカル) | final |
var | 通常の変数 |
ただし Kotlin の val プロパティは「setterがないプロパティ」 という点で、Javaの final フィールド と完全一致ではありません。
実務での判断基準まとめ
基本ルール
まず
valを使う。必要になったらvarにする。
val が適する場面
- 計算結果
- 設定値
- DTO / Entity
- 引数
- 不変な状態
var が適する場面
- UIの状態管理
- 編集中の値
- 明確に状態遷移があるロジック
まとめ
valは「再代入できないこと」を保証するだけで、
「値や状態が不変であること」までは保証しない。
varは状態変化を許可する明示的な選択である。
この理解があれば、Kotlinの var / val で迷うことはほぼなくなります。
以上、Kotlinのvarとvalの違いについてでした。
最後までお読みいただき、ありがとうございました。










