12

我有一个关于 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;
    }

}

所以我的问题是哪种方法更好?

4

5 回答 5

25

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

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

    //getter and setter...
}
  1. 在 JSF 的上下文中,通常不赞成在 getter 和 setter 中进行任何初始化的做法。查看为什么 JSF 多次调用 getter

  2. 此外,根据 的 API@PostConstruct,合约指定了安全特性,并保证如果在这样注释的方法中抛出异常,则不应将 bean 投入使用。普通构造函数没有这样的保证。

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

编辑:重要的是要注意any只能有一个 ,所以所有重要的初始化都应该在那里发生。@PostConstruct@ManagedBean

还值得注意的是,虽然该@PostConstruct方法是初始化支持 bean 变量 / 的理想位置List,但它对托管 bean 的范围有影响

  1. @RequestScoped:在带有此注解的托管 bean 中,每次提交相关的 JSF 视图都会调用该方法。每个请求都会销毁并重新创建一个@RequestScopedbean,这意味着根据您的设置,@PostConstruct在每个请求期间初始化的列表可能会重置为空值或默认值。在某些情况下,由于重新初始化列表 mid-JSF 请求,可能会发生转换错误。

  2. @ViewScoped:在带有此注解的托管 bean 中,当且仅当您正在处理该bean的同一个实例时,才能保证该@PostConstruct方法运行一次。如果 viewscoped bean 被销毁并重新创建,则该方法将再次运行。@ViewScoped@PostConstruct

  3. @SessionScoped: 带有此注解的 bean 被创建一次,并一直保持活动状态,直到用户的 HTTP 会话结束。在这种情况下,@PostConstruct方法保证运行一次且只运行一次,直到 bean 被销毁

也可以看看

于 2013-04-02T20:53:22.680 回答
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);
     }
}
于 2013-04-02T20:11:15.170 回答
3

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

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

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

public Person(ArrayList<> friends) {
    this.friends = friends;//friends
}
于 2013-04-02T20:09:20.153 回答
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);
于 2013-04-02T20:11:52.790 回答
1

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

于 2013-04-02T20:10:09.563 回答