我有一个关于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;
}
}
还是这样更好,在其他类(例如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...
}
在getter和setter中进行任何初始化的做法在JSF上下文中通常是不受欢迎的。参见为什么JSF多次调用getter
此外,根据
@PostConstruct
的API,契约指定了安全特性,并保证如果在这样注释的方法中抛出异常,bean不应该被投入服务。在普通构造函数中没有这样的保证。在托管bean中,注入在构造之后立即发生。这意味着你在构造函数中执行的任何操作都不能依赖于任何注入的资源(通过
@ManagedProperty
)。而在@PostConstruct
方法中,您可以访问在托管bean 上声明的所有资源
编辑:重要的是要注意,对于任何@ManagedBean
, 只能有一个 @PostConstruct
,因此所有重要的初始化都应该发生在那里。
@PostConstruct
方法是初始化支持bean变量/List
的理想位置,但是对于托管bean
的作用域有一些影响。@RequestScoped
:在带有此注释的托管bean中,每次提交相关的JSF视图时都会调用该方法。@RequestScoped
bean在每次请求时被销毁并重新创建,这意味着根据您的设置,在@PostConstruct
中初始化的列表可能在每次请求期间被重置为空或默认值。在某些情况下,由于在jsf请求中间重新初始化列表,可能会发生转换错误。@ViewScoped
:在具有此注释的托管bean中,保证@PostConstruct
方法运行一次,当且仅当处理的是@ViewScoped
bean的相同实例。如果viewscoped bean被销毁并重新创建,@PostConstruct
方法将再次运行。@SessionScoped
:具有此注释的bean被创建一次,并保持活动,直到用户的HTTP会话结束。在这个场景中,@PostConstruct
方法保证只运行一次,直到bean被销毁
参见
- https://stackoverflow.com/a/3406631/1530938
我的建议是:
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
}
我的建议是,在getter中添加一个null检查:
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);
看情况。通常第一种方式更可取,因为稍后可能需要向集合中添加某些内容。如果你不知道你的集合是否初始化,你必须每次都检查。