在JSF托管bean中初始化List

时间:2013-04-02 20:05:42

标签: jsf jsf-2 arraylist java-ee-6

我有一个关于POJO中List的初始化的问题,因为它遵循下一个代码:

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

}

OR是这样的更好,并且在其他类中有初始化(例如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;
    }

}

所以我的问题是什么方法更好?

5 个答案:

答案 0 :(得分:24)

如果它是您所说的托管bean,则应在使用@PostConstruct注释的方法中执行此操作

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

    //getter and setter...
}
  1. 在getF和setter中进行任何初始化的做法通常在JSF的上下文中不受欢迎。请参阅Why JSF calls getters multiple times

  2. 此外,per the API for @PostConstruct,合同指定了安全功能,并保证如果在注释为此类的方法中抛出异常,则不应将该bean投入使用。在普通构造函数上没有这样的保证。

  3. 在托管bean中,注入在施工后立即发生。这意味着您在构造函数中执行的任何操作都不能依赖于任何注入的资源(通过@ManagedProperty)。而在@PostConstruct方法中,您可以访问托管bean上声明的所有资源

  4. 编辑:重要的是要注意对于任何@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被销毁

    4. 另见

答案 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);
     }
}

答案 2 :(得分:3)

在我看来,最好在构造函数中处理它。如果使用默认构造函数,请在构造函数中初始化列表。

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

如果使用接受参数的构造函数,则让调用类传入列表。

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

答案 3 :(得分:2)

我的建议是,在getter中添加一个空检查:

public class Person {
  //other fields...
  private List<String> friends;

  public List<String> getFriends() {
     if (this.friends == null) friends = new ArrayList<String>();
     return friends;
  }
}

但是请注意我省略了setter。相反,在任何客户端代码中,调用如下:

personInstance.getFriends().add("Some Item");

或者,如果您要添加完整列表:

personInstance.getFriends().addAll(someStringCollection);

答案 4 :(得分:1)

这取决于。通常第一种方式更可取,因为您可能希望稍后向集合添加内容。如果您不知道您的收藏集是否已初始化,则必须每次都进行检查。