[Java]staticを初心者向けに解説

# Java初学者に向けて
Java初学者がだいたいよくわからなくて詰まりがちなstaticをなるべくわかりやすくなると思って解説していきます。

# クラスとインスタンス
まずはここの違いを認識しましょう。

クラスとは設計図です。
```java
// ロボットの設計図
public class Robot{
    private String name;
    
    public Robot(){
    }
    
    public Robot(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }
}
```

インスタンスとは、設計図を基につくったオブジェクトです。
```java
    public static void main(String args[]){
        Robot dora = new Robot("ドラえもん");
        Robot koro = new Robot("コロ助");
        Robot arare = new Robot("則巻アラレ");
    }
```
この場合、ドラえもんとコロ助とアラレちゃんができました。

この時、クラス（設計図）のnameはstaticがついていないインスタンスフィールドとなります。

インスタンスフィールドは各インスタンスが別々に持つことができるフィールドなので、
doraというインスタンスのnameはドラえもんですし、
koroというインスタンスのnameはコロ助、arareのnameは則巻アラレです。

```diff_java
// ロボットの設計図
public class Robot{
    private String name;
+   private static String serifu = "私はロボットです"; 
    public Robot(){
        this.name = "ロボット";
    }
    
    public Robot(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

+   public String getSerifu(){
+       return serifu;
+   }

+   public void setSerifu(String kimezerifu){
+       serifu = kimezerifu;
+   }
```

ではここにstaticフィールド`serifu`を足してみましょう。
staticのついたフィールドはクラスフィールドと呼ばれます。
つまり設計図そのものが持つフィールドです。インスタンスが持っているわけではありません。

ドラえもんもコロ助もアラレちゃんも、あなたのserifuは何ですか？と聞かれたら設計図のserifuの内容を答えます。

```java
    dora.getSerifu(); // ドラえもん「私はロボットです」
    koro.getSerifu(); // コロ助「私はロボットです」
    arare.getSerifu();// アラレちゃん「私はロボットです」
```

とても冷たい。まるで機械。

ではこうしてみましょう。
```java
    public static void main(String args[]){
        Robot dora = new Robot("ドラえもん");
        Robot koro = new Robot("コロ助");
        Robot arare = new Robot("則巻アラレ");

        dora.setSerifu("僕ドラえもんです");
        koro.setSerifu("ワガハイはコロ助ナリ");
        arare.setSerifu("んちゃ！アラレだよ！");
    }
```

キャラ付けです。さてこの状態であなたのserifuは？と聞いたらどうなるでしょうか？

```java
    dora.getSerifu(); // ドラえもん「んちゃ！アラレだよ！」
    koro.getSerifu(); // コロ助「んちゃ！アラレだよ！」
    arare.getSerifu();// アラレちゃん「んちゃ！アラレだよ！」
```

こうなります。`setSerifu`では設計図のserifuを書き換えているので、最後に上書きされたものを答えてしまいます。
設計図は1枚しかなく、そこのserifuを書き換えており、ドラえもんたちは聞かれたタイミングで設計図を目で確認して返事しています。
（設計図の内容が変わってるかもしれませんから）
***
各インスタンスごとに違う値を持たせたい場合はstaticは付けないようにしましょう。

```diff_java
// ロボットの設計図
public class Robot{
    private String name;
-   private static String serifu = "私はロボットです"; 
+   private String serifu = "私はロボットです"; 
    public Robot(){
        this.name = "ロボット";
    }
    
    public Robot(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    public String getSerifu(){
-       return serifu;
+       return this.serifu;
    }

    public void setSerifu(String kimezerifu){
-       serifu = kimezerifu;
+       this.serifu = kimezerifu;
    }
```
```diff_java
    public static void main(String args[]){
        Robot dora = new Robot("ドラえもん");
        Robot koro = new Robot("コロ助");
        Robot arare = new Robot("則巻アラレ");

        dora.setSerifu("僕ドラえもんです");
        koro.setSerifu("ワガハイはコロ助ナリ");
        arare.setSerifu("んちゃ！アラレだよ！");

        dora.getSerifu(); // 僕ドラえもんです
        koro.getSerifu(); // ワガハイはコロ助ナリ
        arare.getSerifu();// んちゃ！アラレだよ！
    }
```

# staticの使いどころ
初学者の時点ではstaticなフィールドはあまり使う機会も無いでしょう。
最も使うのは定数です。
定数をわざわざ各インスタンスに持たせておく必要はありません。
もしも同じクラスからインスタンスを1,000個作成した時に定数がstaticになっていないと、
1,000個分の定数が同時に作られ、メモリの無駄遣いになります。

カウンターに使うなどもありますがその辺はもう少し詳しい解説をしている記事に譲ることにします。