2013-04-02 153 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,那么您还需要一个无参数构造函数。 –