Java入門 #25 - static と final の基本

入門 | 10分 で読める | 2026.05.02

公式ドキュメント

今回やること

staticfinalは役割が違います。staticはクラス全体で共有するため、finalは一度代入した参照や値を再代入しないために使います。

学校のメンバーを表すクラスで、次の3つを確認します。

  • 全メンバーで共有する作成人数:static
  • 作成後に変えない個人ID:final
  • 全員が共通で使う学校名:static final
宣言意味呼び出し方
static int countクラスに1つの共有値SchoolMember.count
final int id初期化後に再代入しない値member.id
static final String SCHOOL_NAMEクラス共通の定数SchoolMember.SCHOOL_NAME

オブジェクトを2つ作った時の個数を比べます。

メンバー通常のフィールドstaticフィールド
1人目nameidを1組持つcountを共有する
2人目別のnameidを持つ同じcountを見る

staticは「どこからでも自由に使える」という意味ではありません。誰が変更してよいか分かりにくい共有状態は、増やしすぎないことが大切です。

1. staticで人数を共有する

通常のフィールドはオブジェクトごとに別々です。staticフィールドは、どのオブジェクトから見ても同じ1つの値です。

static int count = 0;

コンストラクタでcountを増やすと、何人作られたかをクラス全体で数えられます。

staticメソッドもインスタンスなしで呼び出せます。例えばMath.max(3, 5)Mathオブジェクトを作らずに使います。一方、showInfo()は各メンバーのnameidを使うため、インスタンスメソッドです。

2. finalでIDを固定する

final int id;

finalフィールドは、コンストラクタで一度だけ代入できます。その後にid = 99と再代入するとコンパイルエラーです。

宣言時に値を決められない場合でも、すべてのコンストラクタが必ず一度代入すればfinalフィールドを使えます。この例では作成人数を増やした直後の値をIDにしています。

ただし、finalは「オブジェクトの中身がすべて不変」という意味ではありません。ここでは数値IDを変えない用途に限定します。

3. static finalで定数を作る

全員に共通し、途中で変更しない学校名は定数にします。

static final String SCHOOL_NAME = "Ada High School";

定数名はSCHOOL_NAMEのように、大文字とアンダースコアで書く慣例があります。

文字列をコード中へ何度も直接書く代わりに定数へまとめると、意味と変更箇所が明確になります。ただし、環境ごとに変わるURLや秘密情報はコード定数にせず、設定や環境変数として扱います。

完成コードを動かす

StaticFinalDemo.javaとして保存します。

class SchoolMember {
    static final String SCHOOL_NAME = "Ada High School";
    static int count = 0;

    final int id;
    String name;

    SchoolMember(String name) {
        count++;
        id = count;
        this.name = name;
    }

    void showInfo() {
        System.out.println(id + ": " + name + " / " + SCHOOL_NAME);
    }
}

public class StaticFinalDemo {
    public static void main(String[] args) {
        SchoolMember first = new SchoolMember("Ada");
        SchoolMember second = new SchoolMember("Ken");

        first.showInfo();
        second.showInfo();
        System.out.println("人数: " + SchoolMember.count);
    }
}
javac StaticFinalDemo.java
java StaticFinalDemo

countSCHOOL_NAMEはオブジェクトではなくクラスに属するため、SchoolMember.countのようにクラス名から読むと意図が明確です。

実行中の値の変化は次のとおりです。

タイミングcount新しいid
クラス読み込み後0
Adaを作成後11
Kenを作成後22

idは各オブジェクトに保存され、countだけが次の作成でも共有されます。

成功確認

1: Ada / Ada High School
2: Ken / Ada High School
人数: 2

2つのオブジェクトが同じ学校名と人数を共有し、IDだけはそれぞれ異なることを確認します。

final classとfinal methodの補足

final classは継承できないクラス、finalメソッドは子クラスでオーバーライドできないメソッドです。再代入禁止とは対象が異なります。API設計上、継承による変更を許したくない時に使いますが、入門ではフィールドと定数を先に使えるようにしましょう。

よくあるつまずき

staticへ何でも置く

利用者ごとの名前や状態をstaticにすると、全オブジェクトで値が共有されます。オブジェクト固有の値は通常のフィールドにします。

finalなら参照先も完全に変わらないと思う

参照型のfinalは、別オブジェクトへの再代入を禁止します。参照しているオブジェクト自体の変更可否は、そのクラスの設計によります。

定数を小文字で書く

動作はしますが、通常のstaticフィールドと区別しにくくなります。static finalの定数は大文字で表します。

練習

図書館利用者を表すLibraryUserを作ってください。全員共通の図書館名をstatic final、作成人数をstatic、変更しない会員番号をfinalで表します。2人作って結果を表示してください。

次のステップ

Java入門シリーズの基礎はここまでです。Python・JavaScript・Javaの違いで各言語の得意分野を確認し、これまでのクラスとコレクションを使った小さな作品を作りましょう。

参考リソース

← 一覧に戻る
PR
PR
PR
PR