Kotlinのvarとvalの違いについて

採用はこちら

Kotlinにおける varval の違いは、単なる文法上の話ではありません。

コードの安全性・可読性・設計思想に直結する重要な概念です。

ここでは、よくある誤解を避けつつ、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状態
  • 編集途中の値
  • 明確に「変わる」ことが前提のデータ

valconst val の違い

val x = 10
const val Y = 10
項目valconst val
再代入不可不可
コンパイル時定数×
宣言場所どこでもトップレベル / object / companion object
任意プリミティブ・String など限定

const val本当の意味での定数 です。

Javaとの対応関係

KotlinJava
val(ローカル)final
var通常の変数

ただし Kotlin の val プロパティは「setterがないプロパティ」 という点で、Javaの final フィールド と完全一致ではありません。

実務での判断基準まとめ

基本ルール

まず val を使う。必要になったら var にする。

val が適する場面

  • 計算結果
  • 設定値
  • DTO / Entity
  • 引数
  • 不変な状態

var が適する場面

  • UIの状態管理
  • 編集中の値
  • 明確に状態遷移があるロジック

まとめ

val は「再代入できないこと」を保証するだけで、
「値や状態が不変であること」までは保証しない。

var は状態変化を許可する明示的な選択である。

この理解があれば、Kotlinの var / val で迷うことはほぼなくなります。

以上、Kotlinのvarとvalの違いについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次