[備忘録 その１１] Java Silver ～クラス定義・オブジェクトの使用 その３～

# static変数とstaticメソッド
クラスに関連付けられており、インスタンスではなくクラス自体によって共有されます。これにより、すべてのインスタンス間で共通のデータや振る舞いを持つことができます。

## static変数(クラス変数)
* 定義：クラスレベルで宣言された変数であり、クラスに一度だけメモリが割り当てられます。クラスのすべてのインスタンスで共有され、どのインスタンスからでもアクセスできます。
* 特徴：
  * クラスがメモリにロードされるときに一度だけ初期化されます。
  * インスタンス変数(非static変数)とは異なり、各インスタンスごとに異なる値を持つのではなく、すべてのインスタンス間で同じ値を共有します。
  * クラス名を通じて直接アクセスできます。　 
```java
public class Example {
    public static int staticVariable = 0; // static変数

    public void increment() {
        staticVariable++;
    }
}

public class Main {
    public static void main(String[] args) {
        Example obj1 = new Example();
        Example obj2 = new Example();

        obj1.increment();
        obj2.increment();

        // どのインスタンスからアクセスしても同じ値が取得される
        System.out.println(Example.staticVariable); // 出力: 2
    }
}
```
## staticメソッド
* 定義：クラスレベルで定義され、クラスそのものに関連付けられたメソッドです。インスタンスを作成せずに、クラス名を使用して直接呼び出すことができます。
* 特徴：
  * インスタンス変数やインスタンスを直接参照することはできません。これはstaticメソッドはクラスに属しているため、特定のインスタンスに依存しないためです。
  * クラス変数(static変数)やほかのstaticメソッドに直接アクセスできます。
  * ユーティリティメソッドとしてよく使用されます。
```java
public class MathUtils {
    public static int add(int a, int b) {
        return a + b;
    }

    public static int multiply(int a, int b) {
        return a * b;
    }
}

public class Main {
    public static void main(String[] args) {
        // staticメソッドの呼び出し
        int sum = MathUtils.add(5, 10);
        int product = MathUtils.multiply(5, 10);

        System.out.println("Sum: " + sum); // 出力: Sum: 15
        System.out.println("Product: " + product); // 出力: Product: 50
    }
}
```
## staticイニシャライザ
クラスが初めてロードされる際に実行される特別なブロックで、static変数の初期化に使用されます。クラスのすべてのインスタンスに共通の初期化処理を一度だけ行うに便利です。

### staticイニシャライザの構文
```java
public class MyClass {
    // static変数
    private static int staticVariable;

    // static初期化子ブロック
    static {
        // 初期化処理
        staticVariable = 10;
        System.out.println("Static initializer block executed.");
    }

    // コンストラクタ
    public MyClass() {
        System.out.println("Constructor called.");
    }

    public static void main(String[] args) {
        // クラスがロードされるときにstatic初期化子ブロックが実行される
        MyClass obj = new MyClass(); // 出力: Static initializer block executed. Constructor called.
    }
}
```
#### 特徴
1\. __クラスがロードされる際に一度だけ実行__：staticイニシャライザは、クラスが初めてメモリにロードされたときに一度だけ実行されます。このタイミングでstatic変数の初期化が行われます。
2\. __実行順序__：static初期化子ブロックは、クラスの最初のインスタンスが作成される前に、またはクラスのstaticメソッドやstaticフィールドに初めてアクセスされたときに実行されます。
3\. __初期化のための複雑なロジック__：通常のstatic変数の初期化では対応できない複雑な初期化が必要な場合に使用します。
4\. __複数のstatic初期化子ブロック__：クラスには複数のstatic初期化子ブロックを持つことができます。これらはソースコードに書かれた順に実行されます。

```java
public class Example {
    private static int staticValue;

    static {
        staticValue = 42;
        System.out.println("Static initializer block called. staticValue = " + staticValue);
    }

    public static void main(String[] args) {
        // クラスがロードされるときにstatic初期化子ブロックが実行される
        System.out.println("Main method called. staticValue = " + staticValue);
    }
}
```
出力は次のようになります。
```java
Static initializer block called. staticValue = 42
Main method called. staticValue = 42
```

# アクセス修飾子とカプセル化
アクセス修飾子とカプセル化は、オブジェクト指向プログラミングの基本的な概念で、データの隠蔽やクラスメンバへのアクセス制御を行うための重要の要素です。

## アクセス修飾子
アクセス修飾子は、クラス、メソッド、変数などのメンバに対するアクセス範囲を制御します。
1 \. __public__
* __アクセス範囲__：クラス内外、同じパッケージ内外のどこからでもアクセス可能です。
* __使用例__：すべてのクラスからアクセス可能にしたいメソッドやフィールドに使用します。
2 \. __protected__
* __アクセス範囲__：同じパッケージ内、およびサブクラスからアクセス可能です。
* __使用例__：継承関係にあるアクセスで利用したいメソッドやフィールドに使用します。
3 \. __default__
* __アクセス範囲__：同じパッケージ内からのアクセス可能です。アクセス修飾子を明示的に指定しない場合、このレベルになります。
* __使用例__：
4 \. __private__
* __アクセス範囲__：クラス内のみでアクセス可能です。クラスの外部からアクセスできます。
* __使用例__：クラス内だけで使用するメソッドやフィールドに使用し、外部からの不正なアクセスを防ぎます。
```java
public class Example {
    public int publicVariable;    // どこからでもアクセス可能
    protected int protectedVariable; // 同じパッケージかサブクラスからアクセス可能
    int defaultVariable;           // 同じパッケージ内からのみアクセス可能
    private int privateVariable;   // クラス内のみアクセス可能

    public void publicMethod() {
        // どこからでも呼び出せる
    }

    protected void protectedMethod() {
        // 同じパッケージかサブクラスからのみ呼び出せる
    }

    void defaultMethod() {
        // 同じパッケージ内からのみ呼び出せる
    }

    private void privateMethod() {
        // クラス内のみで呼び出せる
    }
}
```
## カプセル化
オブジェクト指向プログラミングの重要な概念で、データとそれに関連する操作を一つの単位にまとめ、その詳細を外部から隠蔽することを指します。カプセル化により、データの一貫性を保ち、クラスの使用方法を簡単にし、クラスの内部実装を変更します。
### カプセル化の実現方法
1\.__フィールドをprivateにする__：クラスのデータメンバ(フィールド)をprivateとして、直接のアクセスを禁止します。これにより、外部からの不正なデータ操作を防ぐことができます。
2\.__アクセスメソッド(ゲッター)とミューテータメソッド(セッター)を提供する__：フィールドの値を取得するためのgetterメソッドと、フィールドの値を設定するためのsetterメソッドを提供します。これにより、データのアクセスと変更を制御し、バリデーションやロギングなどの追加処理を行うことができます。
```java
public class Person {
    private String name; // privateフィールド
    private int age;     // privateフィールド

    // コンストラクタ
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // ゲッターメソッド
    public String getName() {
        return name;
    }

    // セッターメソッド
    public void setName(String name) {
        this.name = name;
    }

    // ゲッターメソッド
    public int getAge() {
        return age;
    }

    // セッターメソッド
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        } else {
            System.out.println("Invalid age");
        }
    }
}
```

最初のページ
[[備忘録 その１] Java Silver ～Javaプログラミング基礎～](https://qiita.com/MagicShowTime/items/9fcf3a2cb4a7162aafcf "[備忘録 その１] Java Silver ～Javaプログラミング基礎～")

前のページ
[[備忘録 その１０] Java Silver ～クラス定義・オブジェクトの使用 その２～](https://qiita.com/MagicShowTime/items/af25e023f959cc2ded52 "[備忘録 その１０] Java Silver ～クラス定義・オブジェクトの使用 その２～")

次のページ
[[備忘録 その１２] Java Silver ～継承とポリモフィズム その１～](https://qiita.com/MagicShowTime/items/ed70f8e5917ca0c2f757 "[備忘録 その１２] Java Silver ～継承とポリモフィズム その１～")