Java の「static」についてざっくりまとめてみた[Java 初心者]

## はじめに

こんにちは。
プログラミング初心者 Wakinoza と申します。
Java 勉強中に調べたことを記事にまとめています。

十分気をつけて執筆していますが、なにぶん初心者が書いた記事なので、理解が浅い点などあるかと思います。
記事を参考にされる方は、初心者の記事であることを念頭において、お読みいただけると幸いです。
間違い等あれば、指摘いただけると助かります。

## 対象読者

- Java を勉強中の方
- Java SE Bronze 試験を勉強中の方
- Java の「static」や静的メンバーについてざっくり知りたい方

## 目次

1\. インスタンスメンバーと静的メンバー
2\. 静的フィールド
3\. 静的メソッド
4\. 静的メソッドの制約
5\. Java SE Bronze 試験対策の補足

## 本文

### 1\. インスタンスメンバーと静的メンバー

Java の基本単位は、クラスです。すべてのコードはクラス内に存在し、クラスからインスタンスを生成することで、さまざまな処理を実行しています。

クラスには、初期値を規定する「コンストラクタ」、値を保持する「フィールド」、振る舞いを表す「メソッド」などの要素が含まれます。
これらのクラス内の要素をまとめて「メンバー」と呼びます。

クラスのメンバーは、本来クラスから生成したインスタンスが保持するためものです。インスタンスが保持するメンバーを「インスタンスメンバー」と呼びます。インスタンスメンバーがメインの用途であることは事実ですが、メンバーをちょっと違う用途で使いたい場合もあります。
そんな場面で用いるのが、「static」キーワードです。

「static」は、メンバーをクラス単位で用いたいときにつけるキーワードです。フィールドやメソッドを宣言する際に、型の前に「static」キーワードを入れることで、static なメンバー、つまり「静的メンバー」とすることができます。（静的メンバーは「スタティックメンバー」「クラスメンバー」とも呼ばれます）

静的メンバーは、クラスが保持します。クラスごとに保持されるとは、同じクラスから生成されたインスタンス全てが同じメンバーを共有しているということです。財布で例えると、インスタンスメンバーが個人の財布なら、静的メンバーが家族内の共有財布といったところでしょうか。誰でも使える一つの財布を、家族全員で共有しているようなイメージです。

「インスタンスメンバー」と「静的メンバー」は、何が違うのでしょうか？
それは、①メンバーの影響範囲  ②利用開始のタイミングです。

① メンバーの影響範囲
インスタンスメンバーは、同じクラスから生成されたインスタンスであっても、互いに独立しています。つまり、あるインスタンスの値が変わって、同じクラスから生成された別のインスタンスの値は変化しないということです。
静的メンバーは、同じクラスで生成されたインスタンス全てが、同じ参照を共有します。つまり、あるインスタンスが静的メンバーの値を変化させたら、同じクラスから生成された別のインスタンスの値も変化しているということです。
再度財布で例えると、自分以外の誰かが共有財布のお金を使ったら、共有財布の中身は減ってしまうとイメージです。

② 利用開始のタイミング
インスタンスメンバーは、インスタンスが保持するものなので、インスタンス生成前に利用することはできません。
しかし、静的メンバーは、クラスが保持するものなので、インスタンス生成前も利用することができます。

ここまででインスタンスメンバーと静的メンバーの違いを説明してきました。
次は、メンバーのうち、静的フィールドと静的メソッドをそれぞれ見ていきます。

### 2\. 静的フィールド

静的フィールドは、クラスが保持するフィールドです。
フィールド宣言時に、以下のコードのように、型の前に「static」キーワードを記述することで、静的フィールドとなります。

```Java
public class Wallet{
    public static int sharedWallet; 
    //静的フィールドにする場合は、「static」をつける
    public int myWallet;  
    //インスタンスフィールドにする場合は「static」は不要
}
```

静的フィールドにアクセスする場合は、クラス名.フィールド名とします。
インスタンスを生成している場合、インスタンス変数名.フィールド名でもアクセス可能です。しかし、インスタンスフィールドと混同するリスクもあるため、静的メンバーはクラス名でアクセスするのが一般的です。

```Java
public class Main {
    public static void main(String[] args) {
        Wallet.sharedWallet = 10000;  
        //インスタンス生成前にも利用できる
        System.out.println(Wallet.sharedWallet); //結果：10000

        Wallet w1 = new Wallet();
        Wallet w2 = new Wallet();
        w1.sharedWallet += 500;  
        //非推奨だが、インスタンス名でも静的フィールドは利用できる
        System.out.println(Wallet.sharedWallet); //結果：10500

        w2.sharedWallet += 5000;   
        //非推奨だが、インスタンス名でも、静的フィールドは利用できる
        System.out.println(Wallet.sharedWallet); //結果：15500
  }
}
```

静的フィールドは、インスタンス間で定数を共有する場合などに用いられます。定数の宣言時は「public static final 」の3点セットを利用します。

```Java
public static final double PI = 3.14;
```

### 3\. 静的メソッド

静的メソッドは、クラスが保有するメソッドです。
静的フィールドと同様に、メソッド宣言時、型の前に「static」キーワードを記述することで、静的メソッドとなります。

```Java
public class Wallet{
    public static int sharedWallet;
    public int myWallet;

    public static int getSharedWallet(){ 
    //型の前に「static」を入れると静的メソッドとなる 
        return sharedWallet;
    }
}
```

アクセス方法も、静的フィールドと同様です。クラス名.メソッド名で、静的メソッドにアクセスできます。
インスタンスを生成している場合、インスタンス変数名.メソッド名でもアクセス可能です。

```Java
public class Main {
    public static void main(String[] args) {
        Wallet.sharedWallet = 10000; 
        System.out.println(Wallet.getSharedWallet()); 
        //結果：10000  インスタンス生成前にも利用できる
  }
}
```

静的メソッドは、実際のコーディングではあまり見かけませんが、APIなどで利用されています。例としては、静的メソッドとして用意されているJava.lang.Integerクラスなどがあります。newせずに利用できるため、JVMの負担が少なく済みます。
他にも、性能や管理上の理由から、外部からのインスタンスかを禁止しているAPIなどでは、インスタンス生成を担う静的メソッドが別に準備されています。

静的メソッドをコーディングする機会は少ないですが、開発者はその恩恵をしっかり受けているのです。

### 4\. 静的メソッドの制約
静的メソッドには、注意すべき制約があります。
それは、静的メソッドは静的フィールドや静的メソッドしか利用できないという点です。

実は、インスタンスメンバーは静的メンバーにアクセスできますが、静的メンバーはインスタンスメンバーにアクセスできません。
その原因は、インスタンスメンバーと静的メンバーの利用開始タイミングの差にあります。

静的メソッドは、インスタンス生成前に利用できます。それは言い換えると、インスタンスメンバーが存在しないタイミングでも、静的メンバーは利用できてしまうということです。このタイミングで静的メンバーがインスタンスメンバーにアクセスしても、インスタンス生成前にインスタンスメンバーは存在しないため、エラーになります。こういった挙動を防ぐため、静的メンバーはそもそもインスタンスメンバーにアクセスできない仕組みとなっているのです。

逆に、インスタンス生成時は、常に静的メソッドは利用できる状態です。そのため、インスタンスメンバーは、静的メンバーに自由にアクセスできるのです。

### 5\. Java SE Bronze 試験対策の補足

- 静的メンバーを宣言する場合、アクセス修飾子と static キーワードを逆順に書いても問題ありません。下のコードで言えば、① の順が一般的な書き方ですが、② の逆順の書き方でも問題なく処理が実行されます

```Java
public static int number;  //①一般的な書き順
static public int number2; //②staticとpublicが逆順　これでも問題ない
```

## まとめ

- 「static」キーワードをつけることで、静的メンバーを宣言することができます
- 静的メンバーはクラスが保持するメンバーです。クラス名でアクセスし、同じクラス内で１つの参照を共有します。また、インスタンス生成前から利用することができます
- インスタンスメンバーは静的メンバーにアクセスできますが、逆はできません

---

記事は以上です。
最後までお読みいただき、ありがとうございました。

## 参考文献

この記事は以下の情報を参考にして執筆しました。

- [徹底攻略 Java SE Bronze 問題集]
- [スッキリわかる Java 入門 第４版]
- [パーフェクト Java 改訂 3 版]
- [8.1 スタティックなメンバー（スタティックフィールド、スタティックメソッド、ユーティリティ、クラスのライフサイクルなど）～ Java Basic 編](最終更新 2023-11-05)(https://qiita.com/KenyaSaitoh/items/10e7abd3b38724975a03) (参照 2025-04-16)