对JavaBean创建的一点改进

在看了《Effective Java》Item2中对JavaBean的描述后,再结合Item1和Builder模式,遂想有没有其他方式避免JavaBean创建的线程安全问题呢?

以如下JavaBean类为例,

public class JavaBean {

    private int count;
    private String level;
    private List<String> messages;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    public List<String> getMessages() {
        return messages;
    }

    public void setMessages(List<String> messages) {
        this.messages = messages;
    }
}

分步创建对象如下,因为几个set方法的调用导致对象的状态可能不一致,存在线程安全问题。比如javaBean对象在执行一系列set方法过程中,其他线程调用get方法,这时得到的属性值可能就不对了。

JavaBean javaBean = new JavaBean();
javaBean.setCount(1);
javaBean.setLevel("first");
javaBean.setMessages(new ArrayList<String>());

为了避免创建过程中被访问,可以用匿名对象+链式调用的方式,如下代码,

public class JavaBean {

    private int count;
    private String level;
    private List<String> messages;

    public int getCount() {
        return count;
    }

    public JavaBean setCount(int count) {
        this.count = count;
        return this;
    }

    public String getLevel() {
        return level;
    }

    public JavaBean setLevel(String level) {
        this.level = level;
        return this;
    }

    public List<String> getMessages() {
        return messages;
    }

    public JavaBean setMessages(List<String> messages) {
        this.messages = messages;
        return this;
    }
}
JavaBean javaBean1 = new JavaBean().setCount(1).setLevel("second").setMessages(new ArrayList<String>());
System.out.println(javaBean1.getLevel());

以上写法只有对象完全初始化好后,才将引用赋给javaBean1,避免创建过程中被其他线程访问。

但这个时候,以上分步创建对象的方式仍然可以用。怎么能强制使用链式调用呢?想来想去觉得还得对链式调用进行封装。

增加如下代码,

private JavaBean(){ }

public static JavaBean newInstance(){
    return new JavaBean();
}

public static JavaBean newInstance(int count, String level){
    return new JavaBean().setCount(count).setLevel(level);
}

这样一来,实际上跟直接使用参数化的构造函数一样,如下

public JavaBean(){ }

public JavaBean(int count, String level){
    this.count = count;
    this.level = level;
}

总结:

1. 在写JavaBean时,set方法尽量返回JavaBean类型;

2. 在创建对象时,尽量使用链式调用。

原文地址:https://www.cnblogs.com/hello-yz/p/9844676.html