• 对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. 在创建对象时,尽量使用链式调用。

  • 相关阅读:
    Next Permutation leetcode java
    用户上网行为管理之Panabit
    ROS之冗余线路Recursive Route
    ros的romon功能介绍以及使用条件
    nf_conntrack: table full, dropping packet. 终结篇
    nf_conntrack满之解决方法nginx报502错误
    Ros之BGP学习87-88课
    ros关于动态路由ospf优先级cost和priority的区别和联系
    ros ppp隧道up或者down的时候,可以写脚本,脚本可以调用的参数$user $local-address $remote-address $caller-id $called-id $interface
    ROS 6.X目前限速比较稳定的一个脚本小包优先
  • 原文地址:https://www.cnblogs.com/hello-yz/p/9844676.html
Copyright © 2020-2023  润新知