次のコードに従うので、POJOでのリストの初期化について質問があります。
public class Person {
//other fields...
private List<String> friends=new ArrayList<>();
public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
}
または、このようにして、他のクラス(Bean(JSF)など)で初期化する方がよいですか?
public class Person {
//other fields...
private List<String> friends;
public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
}
だから私の質問は、どのアプローチがより良いかということです。
あなたが言うようにそれがマネージドBeanである場合は、@PostConstruct
アノテーションが付けられたメソッドでこれを行う必要があります。
public class Person {
private List<String> friends;
@PostConstruct
public void init(){
friends = new ArrayList<String>();
}
//getter and setter...
}
ゲッターとセッターで初期化を行う慣行は、一般的にJSFのコンテキスト内で嫌われています。 JSFがゲッターを複数回呼び出す理由 を参照してください。
また、 @PostConstruct
のAPIに従って 、コントラクトは安全機能を指定し、そのように注釈が付けられたメソッドで例外がスローされた場合、Beanがサービスに使用されないことを保証します。プレーンコンストラクターにはそのような保証はありません。
マネージドBeanでは、注入は構築直後に行われます。これは、コンストラクターで実行している操作が、(@ManagedProperty
を介して)注入されたリソースに依存できないことを意味します。一方、@PostConstruct
メソッドでは、マネージドBeanで宣言されたすべてのリソースにアクセスできます。
編集:は任意の@PostConstruct
に対して1つ@ManagedBean
しか存在できないため、すべての重要な初期化はそこで行われる必要があることに注意することが重要です。
@PostConstruct
メソッドはバッキングBean変数/ List
を初期化するのに理想的な場所ですが、マネージドBeanのスコープに関しては影響があることに注意することも価値があります。
@RequestScoped
:このアノテーションが付いたマネージドBeanでは、関連するJSFビューの送信ごとにメソッドが呼び出されます。 @RequestScoped
Beanは、リクエストごとに破棄および再作成されます。これは、セットアップによっては、@PostConstruct
で初期化されたリストが、リクエストごとに空またはデフォルト値にリセットされる場合があることを意味します。特定の状況下では、JSF要求の途中でリストを再初期化した結果として、変換エラーが発生する場合があります。
@ViewScoped
:このアノテーションが付いたマネージドBeanでは、@PostConstruct
メソッドが1回実行されることが保証されていますif and only if@ViewScoped
Beanの同じインスタンスを処理しています。ビュースコープのBeanが破棄されて再作成された場合、@PostConstruct
メソッドが再度実行されます。
@SessionScoped
:このアノテーションが付いたBeanは一度作成され、ユーザーのHTTPセッションが終了するまで存続します。このシナリオでは、@PostConstruct
メソッドは、Beanが破棄されるまで1回だけ実行されることが保証されています。
も参照してください
私はこれを提案します:
public class Person {
//other fields...
private List<String> friends=new ArrayList<>();
// returns a copy to protect original list
public List<String> getFriends() {
Collections.unmodifiableList(new ArrayList<>(friends));
}
public void addFriend(String> friend) {
this.friends.add(friend);
}
public void addFriends(List<String> friends) {
this.friends.addAll(friends);
}
}
私の意見では、コンストラクターでそれを処理するのが最善でしょう。デフォルトのコンストラクターを使用する場合は、コンストラクターでリストを初期化します。
public Person() {
friends = new ArrayList<>();
}
パラメーターを受け入れるコンストラクターを使用する場合は、呼び出し元のクラスにリストを渡させます。
public Person(ArrayList<> friends) {
this.friends = friends;//friends
}
私の提案では、ゲッターにnullチェックを追加します。
public class Person {
//other fields...
private List<String> friends;
public List<String> getFriends() {
if (this.friends == null) friends = new ArrayList<String>();
return friends;
}
}
ただし、セッターを省略していることにも注意してください。代わりに、クライアントコードでは、次のように呼び出します。
personInstance.getFriends().add("Some Item");
または、追加する完全なリストがある場合:
personInstance.getFriends().addAll(someStringCollection);
場合によります。後でコレクションに何かを追加したい場合があるため、通常は最初の方法が望ましいです。コレクションが初期化されたかどうかわからない場合は、毎回チェックする必要があります。