精华内容
下载资源
问答
  • java的两种深度克隆方法,1cloneTest是用Cloneable接口的clone方法实现(对象必须要实现cloneable接口).2cloneSerialize.java是用对象流写对象到byte数组中,然后从byte数组中取得对象.(对象必须要实现serializble接口)
  • java 对象克隆

    2011-10-27 12:47:59
    对象克隆操作过程,展示了对象中数据字段是如何是实现克隆
  • 主要介绍了Java编程实现对象克隆复制)代码详解,涉及了克隆的原因,如何实现克隆,克隆的一般步骤,深克隆与浅克隆的介绍等相关内容,具有一定借鉴价值,需要的朋友可以参考下。
  • java对象复制克隆

    2013-10-28 08:52:09
    深度复制Java对象实例,复制后对象属性值改变不影响被复制对象,有注释
  • Java 对象克隆(clone)

    千次阅读 2017-08-22 10:12:08
    基本数据类型(boolean,char,byte,short,float,double,...按照上面的方法进行对象复制,首先自定义一个汽车类,该类有一个color 属性,然后新建一个汽车实例car,然后将car 赋值给car1 即car1= car; 代码和结果如

    基本数据类型(boolean,char,byte,short,float,double,long)的复制很简单,比如:

    int width = 5int height = width;

    基本数据类型进行这样复制是没有问题的。

    按照上面的方法进行对象的复制,首先自定义一个汽车类,该类有一个color 属性,然后新建一个汽车实例car,然后将car 赋值给car1 即car1= car;
    代码和结果如下:

    public static void main(String[] args) {
    
        Car car = new Car();
        car.setColor("white");
        Car car1 = car;
    
        System.out.println("car color: " + car.getColor());
        System.out.println("car1 color: " + car1.getColor());
    }
    
    
    private static class Car {
    
        private Car() {
        }
    
       private String color;
    
        public void setColor(String color) {
            this.color = color;
        }
    
        public String getColor() {
            return color;
        }
    }

    输出结果:

    car color: white
    car1 color: white

    从打印来看没有什么问题, 那么我们对代码更改如下:

    public static void main(String[] args) {
    
        Car car = new Car();
        car.setColor("white");
        Car car1 = car;
        car1.setColor("blue");
    
        System.out.println("car color: " + car.getColor());
        System.out.println("car1 color: " + car1.getColor());
    }

    输出结果:

    car color: blue
    car1 color: blue

    为什么会出现这种结果呢? 给car1 赋值 结果car 的值也变了。

    问题的原因是,car1= car 这行语句,该语句的作用是将car的引用赋值给car1,其实car 与car1 指向内存堆中的同一个对象,如下图:

    这里写图片描述

    对car 和car1 操作实际上市操作的同一个对象。
    如何复制对象呢 ? 我们知道所有的类都集成Object, 方法如下:

    protected Object clone() throws CloneNotSupportedException {
        if (!(this instanceof Cloneable)) {
            throw new CloneNotSupportedException("Class " + getClass().getName() +
                                                 " doesn't implement Cloneable");
        }
    
        return internalClone();
    }
    
    /*
     * Native helper method for cloning.
     */
    private native Object internalClone();

    从代码中可以看出要实现clone 方法的类必须实现Clonenable 接口,最终是通过native方法,大家都知道native方法是非Java语言实现的代码,供Java程序调用的,因为Java程序是运行在JVM虚拟机上面的,要想访问到比较底层的与操作系统相关的就没办法了,只能由靠近操作系统的语言来实现。
    第一次声明保证克隆对象将有单独的内存地址分配。
    第二次声明表明,原始和克隆的对象应该具有相同的类类型,但它不是强制性的。
    第三声明表明,原始和克隆的对象应该是平等的equals()方法使用,但它不是强制性的。
    因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,但是因为该方法是protected,所以都不能在类外进行访问。要想对一个对象进行复制,就需要对clone方法覆盖。

    为什么要Clone

    有时候需要clone 一个对象修改过的属性,然而通过new创建的对象的属性是初始值,所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。如果把对象的临时属性一个一个的赋值给我新new的对象,操作起来比较麻烦,并且速度没有底层实现的快。

    如何实现clone

    clone 分为两种, 浅克隆(ShallowClone)和深克隆(DeepClone)。在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制,下面将对两者进行详细介绍。

    浅克隆

    1、被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)
    2、 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象。(native为本地方法)

    下面对Car 类进行改造:

    public class TestJava {
    
        public static void main(String[] args) {
    
            Car car = new Car();
            car.setColor("white");
            Car car1 = (Car) car.clone();
            car1.setColor("blue");
    
            if (car1 != null) {
                System.out.println("car color: " + car.getColor());
            }
            System.out.println("car1 color: " + car1.getColor());
    
            System.out.println("car == car1?" + (car == car1));
        }
    
    
        private static class Car implements Cloneable {
    
            private Car() {
            }
    
           private String color;
    
            public void setColor(String color) {
                this.color = color;
            }
    
            public String getColor() {
                return color;
            }
    
            @Override
            protected Object clone() {
                try {
                    return super.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }
    }

    通过查看打印信息可以看出car 和 car1 不是指向的同一个对象,上面实现的这种clone 为浅clone, 还有一种clone 为深clone

    深clone

    我们对Car 类进行改造,增加一个Engine属性

    public class TestJava {
    
        public static void main(String[] args) {
            Engine engine = new Engine();
            engine.setModel("CA");
            Car car = new Car();
            car.setEngine(engine);
            Car newCar = (Car) car.clone();
            newCar.getEngine().setModel("CY");
            System.out.println("Car Engine Model:" + car.getEngine().getModel());
            System.out.println("newCar Engine Model: " + newCar.getEngine().getModel());
        }
    
    
        private static class Car implements Cloneable {
    
            private Car() {
    
            }
    
            private Engine engine;
            private String color;
    
            public void setColor(String color) {
                this.color = color;
            }
    
            public String getColor() {
                return color;
            }
    
            public void setEngine(Engine engine) {
                this.engine = engine;
            }
    
            public Engine getEngine() {
                return engine;
            }
    
            @Override
            protected Object clone() {
                try {
                    return super.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }
    
        private static class Engine {
    
            private String model;
    
            public void setModel(String model) {
                this.model = model;
            }
    
            public String getModel() {
                return model;
            }
        }
    }
    
    
    Car Engine Model:CY
    
    newCar Engine Model: CY

    通过打印可以看改变了newCar对象的Engine 属性 car 的Engine 属性也变了,

    原因是浅复制只是复制了engine变量的引用,并没有真正的开辟另一块空间,将值复制后再将引用返回给新对象。

    所以,为了达到真正的复制对象,而不是纯粹引用复制。我们需要将Engine类可复制化,并且修改clone方法,完整代码如下:

    public class TestJava {
    
        public static void main(String[] args) {
            Engine engine = new Engine();
            engine.setModel("CA");
            Car car = new Car();
            car.setEngine(engine);
            Car newCar = (Car) car.clone();
            newCar.getEngine().setModel("CY");
            System.out.println("Car Engine Model:" + car.getEngine().getModel());
            System.out.println("newCar Engine Model: " + newCar.getEngine().getModel());
        }
    
    
        private static class Car implements Cloneable {
    
            private Car() {
    
            }
    
            private Engine engine;
            private String color;
    
            public void setColor(String color) {
                this.color = color;
            }
    
            public String getColor() {
                return color;
            }
    
            public void setEngine(Engine engine) {
                this.engine = engine;
            }
    
            public Engine getEngine() {
                return engine;
            }
    
            @Override
            protected Object clone() {
                Car car = null;
                try {
                    car = (Car) super.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                    return null;
                }
                car.engine = (Engine) engine.clone();
    
                return car;
            }
        }
    
        private static class Engine implements Cloneable{
    
            private String model;
    
            public void setModel(String model) {
                this.model = model;
            }
    
            public String getModel() {
                return model;
            }
    
    
            @Override
            protected Object clone() {
                try {
                    return super.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }
    }

    输出结果:

    Car Engine Model:CA
    newCar Engine Model: CY

    输出结果与我们的想法一致

    最后Java util 中clone 的实现“

    /**
     * Return a copy of this object.
     */
    public Object clone() {
        Date d = null;
        try {
            d = (Date)super.clone();
            if (cdate != null) {
                d.cdate = (BaseCalendar.Date) cdate.clone();
            }
        } catch (CloneNotSupportedException e) {} // Won't happen
        return d;
    }

    总结 浅克隆 与深克隆

    1、浅克隆

    在浅克隆中,如果原型对象的成员变量是基本类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

    这里写图片描述

    简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

    2、深克隆

    在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

    这里写图片描述

    简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

    序列化实现深克隆

    序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。

    Java语言提供的Cloneable接口和Serializable接口的代码非常简单,它们都是空接口,这种空接口也称为标识接口,标识接口中没有任何方法的定义,其作用是告诉JRE这些接口的实现类是否具有某个功能,如是否支持克隆、是否支持序列化等。

    实现方法:

    public class TestJava {
    
        public static void main(String[] args) {
            Child child = new Child();
            child.name = "Tony";
    
            Parent parent = new Parent();
            parent.setChild(child);
    
            Parent newParent = parent.clone();
            newParent.getChild().name = "Steven";
    
            System.out.println("parent child name:" + parent.getChild().name);
            System.out.println("new parent child name:" + newParent.getChild().name);
        }
    
    
        public static class Parent implements Serializable {
    
            private static final long serialVersionUID = 369285298572941L;
            private Child child;
    
            public void setChild(Child child) {
                this.child = child;
            }
    
            public Child getChild() {
                return child;
            }
    
            public Parent clone() {
                Parent parent = null;
    
                try {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(baos);
                    oos.writeObject(this);
    
                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                    ObjectInputStream ois = new ObjectInputStream(bais);
                    parent = (Parent) ois.readObject();
    
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return parent;
    
            }
        }
    
        public static class Child implements Serializable {
    
            private static final long serialVersionUID = 872390113109L;
    
            public String name;
    
            @Override
            public String toString() {
                return "name :" + name;
            }
        }
    
    
    }

    实现对象克隆有两种方式:

      1). 实现Cloneable接口并重写Object类中的clone()方法;

      2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

    基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。

    展开全文
  • 本篇文章是对java对象复制进行了详细的分析介绍,需要的朋友参考下
  • java学习教程:Java对象克隆(Clone).doc
  • java对象复制

    2014-07-31 21:03:18
    java基础规范以及java对象复制使用
  • 主要介绍了Java对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下
  • 要实现对象克隆,必须满足一下两个条件:1、实现Cloneable接口;2、重新定义clone方法,并指定public访问修饰符。class Vehicle implements Cloneable //浅克隆{ public Vehicle clone() throws ...

    要实现对象的克隆,必须满足一下两个条件:

    1、实现Cloneable接口;

    2、重新定义clone方法,并指定public访问修饰符。

    class Vehicle implements Cloneable  //浅克隆

    {

        public Vehicle clone() throws CloneNotSupportedException

        {

            return (Vehicle) super.clone();

        }

    }

    当为一个引用了对象的变量建立副本时,原变量和副本都是同一个对象的引用,这说明,任何一个变量改变都会影响另一个变量。

    Vehicle original = new Vehicle();

    Vehicle copy = original;

    copy.engine(11) //当设置copy的engine属性的时候,original变量的engine属性也会随着改变。


    如果希望copy是一个新的对象,它的初始状态和original相同,但之后各自会有不同的状态,这种情况下就可以使用clone方法。

    Vehicle original = new Vehicle();

    Vehicle copy = original.clone();

    copy.engine(11)//当设置copy的engine属性的时候,original变量的engine属性不会改变。


    此种克隆模式为浅克隆,如果对象中的所有数据域都是数值或其他基本类型,拷贝这些域是没有任何问题,但如果对象包含子对象的引用,拷贝域就会得到相同子对象的另一个引用,这样原对象和克隆对象仍然会共享一些信息。即在现有Vehicle对象添加一个新的数据域public Driver driver,再使用浅克隆时,driver变量还是会引用同一个对象。


    那么此时,如果想让数据域不共享信息,就要用到深克隆

    class Vehicle implements Cloneable

    {

        public int engine;

        public Driver driver;   //对象;

        public Vehicle clone() throws CloneNotSupportedException

        {

            Vehicle cloned = (Vehicle) super.clone();

            cloned.driver = (Driver) driver.clone();

            return cloned;

        }

    }


    此文是小编参考《Java核心技术 卷 I》第六章第二节对象克隆 整理而成。

    展开全文
  • java对象复制和属性值复制工具类

    千次阅读 2017-11-30 16:19:10
    两个不同类型的对象中有字段名称不区分大小写的情况下一样,字段含义一样,需要组装到另一个对象中去,然后就写了一个这种工具类 我的类型比较特殊,老系统和新系统的对象命名大小写命名不一致,并且字段相同类型也...

    两个不同类型的对象中有字段名称不区分大小写的情况下一样,字段含义一样,需要组装到另一个对象中去,然后就写了一个这种工具类
    我的类型比较特殊,老系统和新系统的对象命名大小写命名不一致,并且字段相同类型也有不一致的情况,所以自己写了一个,
    不是很完美基本能用。

    温馨提示:
    如果同一种类型的对象 属性字段名equals相等 并且类型一致。则完全可以用commons-beanutils包或者spring包中
    的BeanUtils工具类中的copey属性方法。

    /**
     * 实体类字段值相同的复制
     *
     * @author 隔壁老王 2017年8月18日
     */
    public class CopyBeanUtil {
        static Logger log = LoggerFactory.getLogger(CopyBeanUtil.class);
    
        /**
         * 复制sour里属性不为空的值到obje为空的属性
         *
         * @param obje    目标实体类
         * @param sour    源实体类
         * @param isCover 是否保留obje类里不为null的属性值(true为保留源值,属性为null则赋值)
         * @return obje
         */
        public static Object Copy(Object obje, Object sour, boolean isCover) {
            Field[] fields = sour.getClass().getDeclaredFields();
            for (int i = 0, j = fields.length; i < j; i++) {
                String propertyName = fields[i].getName();
                Object propertyValue = getProperty(sour, propertyName);
                if (isCover) {
                    if (getProperty(obje, propertyName) == null && propertyValue != null) {
                        Object setProperty = setProperty(obje, propertyName, propertyValue);
                    }
                } else {
                    Object setProperty = setProperty(obje, propertyName, propertyValue);
                }
    
            }
            return obje;
        }
    
        /**
         * 复制sour里属性不为空的值到obj里并相加
         *
         * @param obj     目标实体类
         * @param sour    源实体类
         * @param isCover
         * @return obj
         */
        public static Object CopyAndAdd(Object obj, Object sour, boolean isCover) {
            Field[] fields = sour.getClass().getDeclaredFields();
            for (int i = 0, j = fields.length; i < j; i++) {
                String propertyName = fields[i].getName();
                Object sourPropertyValue = getProperty(sour, propertyName);
                Object objPropertyValue = getProperty(obj, propertyName);
                if (isCover) {
                    if (objPropertyValue == null && sourPropertyValue != null) {
                        Object setProperty = setProperty(obj, propertyName, sourPropertyValue);
                    } else if (objPropertyValue != null && sourPropertyValue == null) {
                        Object setProperty = setProperty(obj, propertyName, objPropertyValue);
                    } else if (objPropertyValue != null && sourPropertyValue != null) {
                        Object setProperty = setProperty(obj, propertyName, ((int) sourPropertyValue) + (int) objPropertyValue);
                    }
                }
    
            }
            return obj;
        }
    
    
        /**
         * 得到值
         *
         * @param bean
         * @param propertyName
         * @return
         */
        private static Object getProperty(Object bean, String propertyName) {
            Class clazz = bean.getClass();
            try {
                Field field = clazz.getDeclaredField(propertyName);
                Method method = clazz.getDeclaredMethod(getGetterName(field.getName(),field.getType()), new Class[]{});
                return method.invoke(bean, new Object[]{});
            } catch (Exception e) {
            }
            return null;
        }
    
        /**
         * 给bean赋值
         *
         * @param bean
         * @param propertyName
         * @param value
         * @return
         */
        private static Object setProperty(Object bean, String propertyName, Object value) {
            Class clazz = bean.getClass();
            try {
                Field field = clazz.getDeclaredField(propertyName);
                Method method = clazz.getDeclaredMethod(getSetterName(field.getName()), new Class[]{field.getType()});
                return method.invoke(bean, new Object[]{value});
            } catch (Exception e) {
            }
            return null;
        }
    
        /**
         * 根据变量名得到get方法
         *
         * @param propertyName
         * @return
         */
        private static String getGetterName(String propertyName) {
            String method ;
            if( propertyName.length()>1&& Character.isUpperCase(propertyName.charAt(1))){
                 method = "get" +propertyName;
            }else{
                method = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
            }
            return method;
        }
    
        /**
         * 根据变量名和类型获取getter方法
         * @param propertyName
         * @param type
         * @return
         */
        private static String getGetterName(String propertyName, Class<?> type) {
            String method ;
            if(type==Boolean.class|| type==boolean.class){
                if("is".equalsIgnoreCase(propertyName.substring(0, 2))){
                    return propertyName;
                }else{
                    return "is" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                }
    
            }
            if( propertyName.length()>1&& Character.isUpperCase(propertyName.charAt(1))){
                method = "get" +propertyName;
            }else{
                method = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
            }
            return method;
        }
    
        /**
         * 得到setter方法
         *
         * @param propertyName 变量名
         * @return
         */
        private static String getSetterName(String propertyName) {
    //        String method = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
            String method ;
            if( propertyName.length()>1&& Character.isUpperCase(propertyName.charAt(1))){
                method = "set" +propertyName;
            }else{
                method = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
            }
            return method;
        }
    
    
        /**
         * 父类集合转成子类集合集合通用方法(子类集合接收父类集合)
         *
         * @param list 父类集合
         * @param <T>  子类
         * @param <E>  父类
         * @return
         */
        public static <T, E> List<T> chang2ChildClassList(List<E> list) {
            List<T> alist = new ArrayList<>();
            for (E o : list) {
                alist.add((T) o);
            }
            return alist;
    
        }
    
        /**
         * 属性copy  复制sour里属性和obje里属性值忽略大小写相同的 ,不为空的值赋值到obje里
         * 如果存在属性复杂类型并为有效值慎用或改进
         *
         * @param obje
         * @param sour
         * @param isCover 是否保留obje里面属性值不为空的字段值
         * @return
         */
        public static Object copyByIgnoreCase(Object obje, Object sour, boolean isCover) {
    
            try {
                Field[] objFields = obje.getClass().getDeclaredFields();
    
                Field[] sourFields = sour.getClass().getDeclaredFields();
                for (int i = 0; i < sourFields.length; i++) {
                    String sourPropertyName = sourFields[i].getName();
                    //获取来源对象的属性值
                    Object propertyValue = getSourPropertyValue(sour, sourPropertyName);
                    for (int j = 0; j < objFields.length; j++) {
    
                        try {
                            String objPropertyName = objFields[j].getName();
                            if (objPropertyName.equalsIgnoreCase(sourPropertyName)) {
                                if (isCover) {
                                    if (getProperty(obje, objPropertyName) == null && propertyValue != null) {
                                        setObjProperty(obje, objPropertyName, propertyValue);
                                    }
                                } else {
                                    setObjProperty(obje, objPropertyName, propertyValue);
                                }
                                break;
                            }
                        } catch (Exception e) {
                            log.error("给目标bean赋值出错,objPropertyName:{},value:{}",sourPropertyName,propertyValue,e);
                            e.printStackTrace();
                        }
                    }
    
                }
            } catch (SecurityException e) {
                e.printStackTrace();
                log.error("给目标bean赋值出错,obje:{},sour:{}", JSON.toJSONString(obje), JSON.toJSONString(sour),e);
            }
            return obje;
        }
    
        /**
         * 根据属性名获取的值
         *
         * @param sourceBean
         * @param sourcePropertyName
         * @return
         */
        private static Object getSourPropertyValue(Object sourceBean, String sourcePropertyName) {
            Class clazz = sourceBean.getClass();
            try {
                Field field = clazz.getDeclaredField(sourcePropertyName);
                Method method = clazz.getDeclaredMethod(getGetterName(field.getName(),field.getType()), new Class[]{});
                return method.invoke(sourceBean, new Object[]{});
            } catch (Exception e) {
                log.error("获取属性名(不区分大小写)相似的值赋值出差", e);
            }
            return null;
        }
    
    
    
        /**
         * 给目标bean赋值
         *
         * @param objBean
         * @param sourcePropertyName
         * @param value
         * @return
         */
        private static Object setObjPropertyBySourceProperty(Object objBean, String sourcePropertyName, Object value) {
            Class clazz = objBean.getClass();
            Field[] fields = clazz.getDeclaredFields();
            try {
                for (int i = 0, j = fields.length; i < j; i++) {
                    String propertyName = fields[i].getName();
                    if (sourcePropertyName.equalsIgnoreCase(propertyName)) {
                        Field field = clazz.getDeclaredField(propertyName);
                        if (field.getType() == BigDecimal.class) {
                            if (value instanceof String) {
                                value = new BigDecimal(String.valueOf(value));
                            } else if (value instanceof Integer || value instanceof Double) {
    //							传double直接new BigDecimal,数会变大
                                value = BigDecimal.valueOf(Double.parseDouble(String.valueOf(value)));
                            }
                        }
                        if (field.getType() == Double.class || field.getType() == double.class) {
                            if (value instanceof BigDecimal) {
                                DecimalFormat df = new DecimalFormat("#.000000");
                                Double v = Double.parseDouble(String.valueOf(value));
                                value = df.format(v);
                            }
                        }
    
                        Method method = clazz.getDeclaredMethod(getSetterName(field.getName()), new Class[]{field.getType()});
                        return method.invoke(objBean, new Object[]{value});
                    }
                }
    
            } catch (Exception e) {
            }
            return null;
        }
    
    
        /**
         * 给目标bean赋值
         *
         * @param objBean
         * @param propertyName
         * @param value
         * @return
         */
        private static Object setObjProperty(Object objBean, String propertyName, Object value) {
            Class clazz = objBean.getClass();
            try {
                Field field = clazz.getDeclaredField(propertyName);
                if (field.getType() == BigDecimal.class) {
                    if (value instanceof String) {
                        value = new BigDecimal(String.valueOf(value));
                    } else if (value instanceof Integer || value instanceof Double) {
    //							传double直接new BigDecimal,数会变大
                        value = BigDecimal.valueOf(Double.parseDouble(String.valueOf(value)));
                    }
                }
                if (field.getType() == Double.class || field.getType() == double.class) {
                    if (value instanceof BigDecimal) {
                        DecimalFormat df = new DecimalFormat("#.000000");
                        Double v = Double.parseDouble(String.valueOf(value));
                        value =new BigDecimal(df.format(v));
                    }
                }
                if (field.getType() == Integer.class || field.getType() == int.class) {
                    if (value instanceof Float) {
                         value = Math.round(Float.parseFloat(String.valueOf(value)));
                    }
                }
                Method method = clazz.getDeclaredMethod(getSetterName(field.getName()), new Class[]{field.getType()});
                log.info("给目标bean赋值,propertyName:{},value:{}",propertyName,value);
                Object obj = method.invoke(objBean, new Object[]{value});
                return obj;
    
            } catch (Exception e) {
                log.error("给目标bean赋值出错,propertyName:{},value:{}",propertyName,value,e);
            }
            return null;
        }
        public static void main(String[] args) {
    //        ReAlarmResult re= new ReAlarmResult();
    //        re.setAlarmContent("sdfsdfsd");
    //        re.setBlat(2.234343);
    //        re.setBlon(34.34324);
    //        ReAlarmResult s = new ReAlarmResult();
    //        s.setAlarmContent("222");
    //        copyByIgnoreCase(s,re,true);
    //        System.out.printf(JSON.toJSONString(s));
    //        BeanUtils.copyProperties();
            //BeanUtils.copyProperties();
        }
    
    }
    
    展开全文
  • Java对象复制四种方式

    千次阅读 2019-03-16 08:57:56
    在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象...

    1、概述
    在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。例如下面程序展示的情况:

    class Student {  
        private int number;  
    
        public int getNumber() {  
            return number;  
        }  
    
        public void setNumber(int number) {  
            this.number = number;  
        }  
    
    }  
    public class Test {   
        public static void main(String args[]) {  
            Student stu1 = new Student();  
            stu1.setNumber(12345);  
            Student stu2 = stu1;  
            stu1.setNumber(54321);  
            System.out.println("学生1:" + stu1.getNumber());  
            System.out.println("学生2:" + stu2.getNumber());  
        }  
    }

    结果:

    学生1:54321 
    学生2:54321

    为什么改变学生2的学号,学生1的学号也发生了变化呢? 
    原因出在(stu2 = stu1) 这一句。该语句的作用是将stu1的引用赋值给stu2, 
    这样,stu1和stu2指向内存堆中同一个对象。如图:

    è¿éå代ç ç

    那么,怎么能干干净净清清楚楚地复制一个对象呢。在 Java语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求有很多途径, 
    (1)将A对象的值分别通过set方法加入B对象中; 
    (2)通过重写java.lang.Object类中的方法clone(); 
    (3)通过org.apache.commons中的工具类BeanUtils和PropertyUtils进行对象复制; 
    (4)通过序列化实现对象的复制。

    2、将A对象的值分别通过set方法加入B对象中
    对属性逐个赋值,本实例为了演示简单就设置了一个属性:

    Student stu1 = new Student();  
    stu1.setNumber(12345);  
    Student stu2 = new Student();  
    stu2.setNumber(stu1.getNumber());

    我们发现,属性少对属性逐个赋值还挺方便,但是属性多时,就需要一直get、set了,非常麻烦。

    3、重写java.lang.Object类中的方法clone()
    先介绍一下两种不同的克隆方法,浅克隆(ShallowClone)和深克隆(DeepClone)。

    在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制,下面将对两者进行详细介绍。

    3.1 浅克隆
    一般步骤:

    被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)

    覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象。(native为本地方法)

    class Student implements Cloneable{  
        private int number;  
    
        public int getNumber() {  
            return number;  
        }  
    
        public void setNumber(int number) {  
            this.number = number;  
        }  
    
        @Override  
        public Object clone() {  
            Student stu = null;  
            try{  
                stu = (Student)super.clone();  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            }  
            return stu;  
        }  
    }  
    public class Test {  
        public static void main(String args[]) {  
            Student stu1 = new Student();  
            stu1.setNumber(12345);  
            Student stu2 = (Student)stu1.clone();  
    
            System.out.println("学生1:" + stu1.getNumber());  
            System.out.println("学生2:" + stu2.getNumber());  
    
            stu2.setNumber(54321);  
    
            System.out.println("学生1:" + stu1.getNumber());  
            System.out.println("学生2:" + stu2.getNumber());  
        }  
    }  

    结果: 
    学生1:12345 
    学生2:12345 
    学生1:12345 
    学生2:54321

    在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

    简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

     è¿éåå¾çæè¿°
    在Java语言中,通过覆盖Object类的clone()方法可以实现浅克隆。3.2 深克隆

    package abc;  
    
    class Address implements Cloneable {  
        private String add;  
    
        public String getAdd() {  
            return add;  
        }  
    
        public void setAdd(String add) {  
            this.add = add;  
        }  
    
        @Override  
        public Object clone() {  
            Address addr = null;  
            try{  
                addr = (Address)super.clone();  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            }  
            return addr;  
        }  
    }  
    
    class Student implements Cloneable{  
        private int number;  
    
        private Address addr;  
    
        public Address getAddr() {  
            return addr;  
        }  
    
        public void setAddr(Address addr) {  
            this.addr = addr;  
        }  
    
        public int getNumber() {  
            return number;  
        }  
    
        public void setNumber(int number) {  
            this.number = number;  
        }  
    
        @Override  
        public Object clone() {  
            Student stu = null;  
            try{  
                stu = (Student)super.clone();   //浅复制  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            }  
            stu.addr = (Address)addr.clone();   //深度复制  
            return stu;  
        }  
    }  
    public class Test {  
    
        public static void main(String args[]) {  
    
            Address addr = new Address();  
            addr.setAdd("杭州市");  
            Student stu1 = new Student();  
            stu1.setNumber(123);  
            stu1.setAddr(addr);  
    
            Student stu2 = (Student)stu1.clone();  
    
            System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());  
            System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());  
    
            addr.setAdd("西湖区");  
    
            System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());  
            System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());  
        }  
    }

    结果: 
    学生1:123,地址:杭州市 
    学生2:123,地址:杭州市 
    学生1:123,地址:西湖区 
    学生2:123,地址:西湖区

    怎么两个学生的地址都改变了?

    原因是浅复制只是复制了addr变量的引用,并没有真正的开辟另一块空间,将值复制后再将引用返回给新对象。

    为了达到真正的复制对象,而不是纯粹引用复制。我们需要将Address类可复制化,并且修改clone方法,完整代码如下:

    package abc;  
    
    class Address implements Cloneable {  
        private String add;  
    
        public String getAdd() {  
            return add;  
        }  
    
        public void setAdd(String add) {  
            this.add = add;  
        }  
    
        @Override  
        public Object clone() {  
            Address addr = null;  
            try{  
                addr = (Address)super.clone();  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            }  
            return addr;  
        }  
    }  
    
    class Student implements Cloneable{  
        private int number;  
    
        private Address addr;  
    
        public Address getAddr() {  
            return addr;  
        }  
    
        public void setAddr(Address addr) {  
            this.addr = addr;  
        }  
    
        public int getNumber() {  
            return number;  
        }  
    
        public void setNumber(int number) {  
            this.number = number;  
        }  
    
        @Override  
        public Object clone() {  
            Student stu = null;  
            try{  
                stu = (Student)super.clone();   //浅复制  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            }  
            stu.addr = (Address)addr.clone();   //深度复制  
            return stu;  
        }  
    }  
    public class Test {  
    
        public static void main(String args[]) {  
    
            Address addr = new Address();  
            addr.setAdd("杭州市");  
            Student stu1 = new Student();  
            stu1.setNumber(123);  
            stu1.setAddr(addr);  
    
            Student stu2 = (Student)stu1.clone();  
    
            System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());  
            System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());  
    
            addr.setAdd("西湖区");  
    
            System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());  
            System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());  
        }  
    }

    结果: 
    学生1:123,地址:杭州市 
    学生2:123,地址:杭州市 
    学生1:123,地址:西湖区 
    学生2:123,地址:杭州市

    在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

    简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。 
     è¿éåå¾çæè¿°
    在Java语言中,如果需要实现深克隆,可以通过覆盖Object类的clone()方法实现,也可以通过序列化(Serialization)等方式来实现。

    (如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。)

    4、工具类BeanUtils和PropertyUtils进行对象复制

    Student stu1 = new Student();  
    stu1.setNumber(12345);  
    Student stu2 = new Student(); 
    BeanUtils.copyProperties(stu2,stu1);

    这种写法无论多少种属性都只需要一行代码搞定,很方便吧!除BeanUtils外还有一个名为PropertyUtils的工具类,它也提供copyProperties()方法,作用与BeanUtils的同名方法十分相似,主要的区别在于BeanUtils提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而PropertyUtils不支持这个功能,但是速度会更快一些。在实际开发中,BeanUtils使用更普遍一点,犯错的风险更低一点。

    5、通过序列化实现对象的复制
    序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。

    要更多干货、技术猛料的孩子,快点拿起手机扫码关注我,我在这里等你哦~

                                                           

    展开全文
  • 对象属性值的复制工具类 1.全复制 2.部分复制 3.部分不复制
  • 编程语言java对象复制.pdf
  • Java如何实现对象克隆

    千次阅读 2019-03-24 11:16:30
    Java中的对象克隆
  • java对象复制[参考].pdf

    2021-10-11 03:33:39
    java对象复制[参考].pdf
  • java复制对象的几种方法

    千次阅读 2020-04-11 15:50:42
    最近业务要复制对象,但我又不想一个个的去get、set,于是就网上找了三种复制对象的方法。 一,浅层复制。 1.需要复制的类实现Cloneable接口; 2.复写clone()方法; import java.lang.Cloneable;; public class ...
  • Java对象复制非空属性

    千次阅读 2019-02-25 15:06:15
    引用org.springframework.beans.BeanUtils类提供的方法copyProperties(Object ... ignoreProperties) 用于对象拷贝,spring 和 Apache都提供了相应的工具类方法,BeanUtils.copyProperties package com.mixislink...
  • Java对象克隆

    2017-02-21 17:35:56
    Java提高篇——对象克隆复制
  • java对象克隆浅析

    2017-05-24 15:43:08
    为什么需要克隆?在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A已经包含了一些有效值,此时可能会需要一个和A完全...克隆的实现方式一、浅拷贝对于要克隆对象,对于其基本数据类型的属性,
  • 对象克隆复制)假如说你想复制一个简单变量。很简单:int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。但是如果你...
  • NULL 博文链接:https://ollevere.iteye.com/blog/1323205
  • 理解java中的对象克隆

    2020-05-24 18:05:10
    理解java中的对象克隆 一、什么是对象克隆 所谓的对象克隆描述的概念就是进行对象的复制,当一个对象完成之后实际上都会自动的开辟内存空间,在每一块堆内存空间里面都会保存有对象的相关属性内容,所谓的对象克隆它...
  • java对象属性复制的几种方式

    千次阅读 2020-09-09 20:25:34
    java对象属性复制的几种方式 1.使用java反射机制,获取对象的属性和get、set方法进行复制; 2.使用spring-beans5.0.8包中的BeanUtils类 import org.springframework.beans.BeanUtils; SourceObject sourceObject = ...
  • java 对象深度复制Today we will look into Java deep copy. Sometimes we want to get a copy of an Object, but java works on reference and if we don’t want to alter the original object then we need to ...
  • Java对象的拷贝与复制

    千次阅读 2018-03-09 15:25:10
    Java对象的Copy引用CSDN博客地址:http://m.blog.csdn.net/chenssy/article/details/12952063拷贝一个Java对象,这种需求在程序中应该常用,一下有两种实现方式,浅拷贝和深度拷贝1.浅拷贝我们知道在Java中存在这个...
  • 在本篇文章中我们给大家分享了关于java对象中浅克隆和深克隆的相关知识点和相关代码内容,有兴趣的朋友们学习下。
  • Java实现对象克隆的方法

    千次阅读 2019-06-20 17:27:26
    转载请注明出处:https://cartoonyu.github.io/cartoon-blog/post/java/java%E5%AE%9E%E7%8E%B0%E5%85%8B%E9%9A%86%E7%9A%84%E6%96%B9%E6%B3%95/ 前言 这也是昨天的面试题。 当时只说了深拷贝以及浅拷贝,面试...
  • Java对象复制和数组复制(拷贝)

    千次阅读 2017-10-05 02:52:23
    浅拷贝:只复制一个对象对象内部存在的指向其他对象数组或者引用则不复制 深拷贝:对象对象内部的引用均复制   对象拷贝 一、对象浅拷贝 Object类里的clone方法是浅复制 1. 实现Cloneable接口,该接口没有任何...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 468,329
精华内容 187,331
关键字:

java对象克隆

java 订阅