【Java】静的 / 非静的フィールド
概要
静的フィールドと非静的フィールドの使い方で不明点があったので、記事を作成。
結論、
- 静的フィールドとは、クラスに属しており、クラスのすべてのインスタンス間で共有されるもの。
- 非静的フィールドとは、各インスタンスに属しており、それぞれのインスタンスで個別に保持されるもの。
各フィールドの説明
静的フィールドはアプリケーション全体で共有されるデータを使用して、非静的フィールドは各インスタンスで固有のデータを使用する。静的フィールドは一度設定されると、アプリケーションのライフサイクル全体を通じて、その値を維持する。一方で非静的フィールドは、新しいインスタンスが生成されるたびに、そのフィールドの値が設定または更新される。
静的フィールド
全インスタンスで共有すべき情報で使われる。ホテルの予約サイトを例に挙げると、管理者視点では、顧客リストはシステム上の全てにおいて、共有されるべきである。例えば、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