2013-04-02 154 views
11

我有一個關於在POJO列表的初始化問題,因爲它遵循了下面的代碼:初始化在JSF託管bean

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; 
    } 

} 

還是這樣好,在其他類initalization(比如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; 
    } 

} 

所以我的問題是什麼方法更好?

+7

如果他們先打電話吸除,你擰緊。 –

+0

它是一個'managedBean'嗎? –

+0

@ Eng.Fouad 是的,它是managedBean。 –

回答

24

如果是像你說的,你應該在做這個託管bean標註了@PostConstruct

public class Person { 
    private List<String> friends; 
    @PostConstruct 
    public void init(){ 
     friends = new ArrayList<String>(); 
    } 

    //getter and setter... 
} 
  1. 在吸氣和setter做任何初始化的實踐方法是通常˚F在JSF的背景下排成一行。見Why JSF calls getters multiple times

  2. 此外,per the API for @PostConstruct,合同規定的安全功能,並保證如果一個例外是這樣的註釋的方法拋出,豆不應該投入服務。簡單的構造函數沒有這樣的保證。

  3. 在託管bean中,注入在構建後立即發生。這意味着您在構造函數中執行的任何操作都不能依賴於任何注入的資源(通過@ManagedProperty)。而在@PostConstruct方法,你將有機會對託管bean聲明的所有資源

編輯:需要注意的是只能有一個@PostConstruct任何@ManagedBean是很重要的,所以所有重要的初始化應該發生在那裏。

這也是值得指出的是,雖然@PostConstruct方法是初始化的理想場所後臺Bean的變量/ List,有關於託管bean

  1. @RequestScoped範圍的影響:在管理有了這個註解的bean,這個方法將在每次提交相關的JSF視圖時被調用。一個@RequestScoped bean被銷燬並且被每個請求重新創建,這意味着根據您的設置,在每個請求期間,在@PostConstruct中初始化的列表可能被重置爲空或默認值。在某些情況下,由於重新初始化列表中JSF請求,可能會發生轉換錯誤。

  2. @ViewScoped:在本註釋的託管bean,你保證有@PostConstruct方法運行一次,當且僅當你處理的@ViewScoped bean的同一個實例。如果viewscoped bean被銷燬並重新創建,@PostConstruct方法將再次運行。

  3. @SessionScoped:具有此註解的bean只創建一次,並保持活動狀態,直到用戶的HTTP會話結束。在這種情況下,@PostConstruct方法是保證運行一次且僅一次,直到bean被銷燬

參見

+0

請任何人都不要編輯我引用的鏈接。我需要它作爲meta – kolossus

+0

的參考。在你的答案中直接添加這個值是很有價值的(直接來自'@ PostConstruct'文檔):*只有一種方法可以用這個註釋來註釋* –

+0

@LuiggiMendoza,好點。謝謝 – kolossus

3

在我看來最好是在構造函數中處理。如果使用默認構造函數,則在構造函數中初始化列表。

public Person() { 
    friends = new ArrayList<>(); 
} 

如果使用接受參數的構造函數,則讓調用類在列表中傳遞。

public Person(ArrayList<> friends) { 
    this.friends = friends;//friends 
} 
+0

在一個託管bean中,處理這個不是最好的在構造函數 – kolossus

+0

是的,我的例子更適合於POJO而不是託管bean。儘管如果你不使用託管屬性,在使用託管bean初始化缺省無參數構造函數時,我認爲沒有任何傷害。 – Haz

+0

對不起,不得不做一個微不足道的編輯來反轉我的投票 – kolossus

1

這取決於。通常情況下,第一種方式更可取,因爲您可能希望稍後添加某些內容到收集中如果您不知道您的收藏是否已初始化,則您必須每次都檢查它。

4

我建議這樣的:

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); 
    } 
} 
+0

你可能想'清除'或在'set'中做一個防禦副本,否則它不是一個真正的setter而是一個'addAll'。 –

+0

@ bmorris591:謝謝我更改了方法名稱以避免混淆。 – anubhava

+1

非常類似於我自己的答案,但也許更好的設計總體上有像這樣的add和addAll方法。我懷疑我們在同一時間打字。 +1 – cobaltduck

2

我的建議,在吸氣添加一個空檢查:

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); 
+0

取決於OP想要的行爲。這是一種稱爲「延遲初始化」的好策略。如果這是一個託管bean,那麼您還需要一個無參數構造函數。 –