拷贝bean方法

以下每一种方法都是一层拷贝(除开序列化反序列化的方式),都是将直接属性进行拷贝赋值

1.实现bean的Cloneable接口

    static class Body implements Cloneable{
        public Head head;
        
        public Body() {}

        public Body(Head head) {this.head = head;}

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
        
    }
    static class Head /*implements Cloneable*/{
        public  Face face;
        
        public Head() {}
        public Head(Face face){this.face = face;}
        
    } 
    public static void main(String[] args) throws CloneNotSupportedException {
        
        Body body = new Body(new Head());
        
        Body body1 = (Body) body.clone();
        
        System.out.println("body == body1 : " + (body == body1) );
        
        System.out.println("body.head == body1.head : " +  (body.head == body1.head));
        
        
    }
  • 只对bean的直接属性进行引用复制,如果直接属性是一个引用那么直接属性并没有实现拷贝,所以上述代码输出为
body == body1 : false
body.head == body1.head : true
  • 只适用于同一种类型的class拷贝转换。
  • 实现比较繁琐,需要拷贝的类都必须去实现clone方法,其他的方式只要有个一类就可以干事了。
  • 效率非常非常高

json转换

以淘宝的fastjson库为例

static class Body {
        public Head head;
        
        public Body() {}

        public Body(Head head) {this.head = head;}
        
    }
    static class Head {
        public  Face face;
        
        public Head() {}
        public Head(Face face){this.face = face;}
        
    } 
    public static void main(String[] args)  {
        
        Body body = new Body(new Head());
        
        Body body1 = JSONObject.parseObject(JSONObject.toJSONString(body), Body.class);
        
        System.out.println("body == body1 : " + (body == body1) );
        
        System.out.println("body.head == body1.head : " +  (body.head == body1.head));
        
        
    }
  • 所有节点,所有层次全部实现深拷贝,以上代码输出为
body == body1 : false
body.head == body1.head : false
  • 转换效率相比其他方式较差,不过fastjson号称fast,算法上做了很多优化,一般性能不十分敏感的应用都可以这样做,至少比apache的beanutil快。

  • 不同class可以相互转换,转换前提是目标class的属性必须包含所有被复制对象的属性

  • 对象全方位深拷贝的最简单实现方式。

  • 类的默认构造器必须存在!!!!!!

BeanUtils工具类(org.springframework.beans.BeanUtils, org.apache.commons.beanutils.BeanUtils等)

static class Body {
        public Head head;
        
        public Body() {}

        public Body(Head head) {this.head = head;}
        
    }
    static class Head {
        public  Face face;
        
        public Head() {}
        public Head(Face face){this.face = face;}
        
    } 
    public static void main(String[] args)  {
        
        Body body = new Body(new Head());
        
        Body body1 = new Body();

                BeanUtils.copyProperties(body, body1);
        
        System.out.println("body == body1 : " + (body == body1) );
        
        System.out.println("body.head == body1.head : " +  (body.head == body1.head));
        
        
    }
  • spring的beanutils其实就是包装了apache的beanutils而已
  • 只对第一层属性进行复制,所以上述代码输出为:
body == body1 : false
body.head == body1.head : true
  • 支持不同的实例间拷贝,不要求被复制对象和目标对象间属性列表必须是包含关系,两个对象属性完全不相同,该方法也不会报错

  • 支持在参数后面添加,ignoreProperty可变参数

cglib库的BeanCopier

static class Body {
        public Head head;
        
        public Body() {}

        public Body(Head head) {this.head = head;}
        
    }
    static class Head {
        public  Face face;
        
        public Head() {}
        public Head(Face face){this.face = face;}
        
    } 
    public static void main(String[] args)  {
        
        Body body = new Body(new Head());
        
        Body body1 = new Body();

                BeanCopier bc = BeanCopier.create(Body.class, Body.class, false);
        bc.copy(f, t, null);
        System.out.println("body == body1 : " + (body == body1) );
        
        System.out.println("body.head == body1.head : " +  (body.head == body1.head));
        
        
    }
  • 其实现效果和beanutils一模一样,都是第一层复制,而且两个对象的属性有没有交集,需不需要全包含都没有要求
  • beancopier支持自己是属性转换器对特殊的属性进行转换,如:
 BeanCopier bc = BeanCopier.create(Body.class, Body.class, true); //这里要设置为true
 bc.copy(f, t, new Converter(){
    @Override
    protected Object convert(Object value, Class target, Object context){
     return null; //这里可以写自己的转换逻辑
    }
});

还有其他的转换方式,暂时没有去探究

性能比较

以上代码分别执行500000次各自的运行时间

  • cglib:239ms
  • beanutils:2624ms
  • json: 791ms
  • jdk clone: 18ms

效率一目了然,然而各自有自己的优缺点和使用场景

你可能感兴趣的:(拷贝bean方法)