【Java】静的 / 非静的フィールド

2024/01/30に公開

概要

静的フィールドと非静的フィールドの使い方で不明点があったので、記事を作成。

結論、

  • 静的フィールドとは、クラスに属しており、クラスのすべてのインスタンス間で共有されるもの。
  • 非静的フィールドとは、各インスタンスに属しており、それぞれのインスタンスで個別に保持されるもの。

各フィールドの説明

静的フィールドはアプリケーション全体で共有されるデータを使用して、非静的フィールドは各インスタンスで固有のデータを使用する。静的フィールドは一度設定されると、アプリケーションのライフサイクル全体を通じて、その値を維持する。一方で非静的フィールドは、新しいインスタンスが生成されるたびに、そのフィールドの値が設定または更新される。

静的フィールド

全インスタンスで共有すべき情報で使われる。ホテルの予約サイトを例に挙げると、管理者視点では、顧客リストはシステム上の全てにおいて、共有されるべきである。例えば、CustomerServiceインスタンスが作成されても、リストはリフレッシュされるべきではなく、既存の顧客リストに追加・削除すべきである。

非静的フィールド

インスタンス固有の情報を扱う際に使われる。ホテルの予約サイトを例に挙げると、ユーザ名、ID、メールアドレスなど。こういった情報は、インスタンスごとに異なる状態を持つ。例えば、ユーザAは自身のユーザ名やメールアドレスも見るし、ユーザBは彼自身の情報をみる。

具体的事例

ホテルの予約アプリを作っていた際に、アプリケーション全体で共有すべき「顧客リスト」を非静的フィールドとして取り扱っていたため、毎回顧客リストを更新するたびにインスタンスが更新されていた。その結果、顧客リストが一人もしくは空の状態となっていた。

問題点

上記で説明した通り、customerListが非静的だと、新しいインスタンスが作成されるたびに、customerListが新しくなる。つまり、既存の顧客情報が失われてしまう。一度新しいCustomerServieインスタンスが作成されると、以前に追加された顧客情報にアクセスできなくなってしまう。

また、アプリケーション内で複数のCustomerServiceインスタンスが作成されると、それぞれのインスタンスが独自のcustomerListを持つため、顧客データが一貫性を欠いてしまう。そのため、一つのインスタンスで追加された顧客は、他のインスタンスでは扱えない。

以下コードのように、customerListが非静的フィールドとして定義されていた。

public class CustomerService {
    private List<Customer> customerList; // これが非静的フィールドとして定義されていた

    public List<Customer> createCustomerList() {
        if (customerList == null || customerList.isEmpty()) {
            customerList = new LinkedList<>();
        }
        return customerList;
    }

    public void addCustomer(String firstName, String lastName, String email) {
        createCustomerList();
        Customer newCustomer = new Customer(firstName, lastName, email);
        customerList.add(newCustomer);
    }

    // 他のメソッド
}

解決策

以下の通り、CustomerServiceクラスのcustomerListを静的フィールドに変更し、createCustomerListを削除することで、解決できる。

public class CustomerService {
    private static List<Customer> customerList = new LinkedList<>(); // 静的フィールドに変更

    public void addCustomer(String firstName, String lastName, String email) {
        Customer newCustomer = new Customer(firstName, lastName, email);
        customerList.add(newCustomer);
    }
    // 他のメソッド
}

Discussion