背景

Java中想要复制对象时,需要考虑到一个问题:如果是引用类型对象,如果只是通过一般的“=”赋值,那么因为只是把引用地址给了新对象,所以改变新对象时会因为实际改变的引用地址指向的对象,因此难免出现改变源对象的属性。例如:

public class Demo1 {
    static class People {
        private String name;
        private String age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAge() {
            return age;
        }

        public void setAge(String age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "People{" +
                    "name='" + name + '\'' +
                    ", age='" + age + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) {
        People people1 = new People();
        people1.setName("zhangsan");
        people1.setAge("23");
        System.out.println("源对象:" + people1);
        People people2 = people1;
        System.out.println("新对象:" + people2);
        people2.setName("lisi");
        System.out.println("修改后的源对象:" + people1);
        System.out.println("修改后的新对象:" + people2);
    }
}

结果:

源对象:People{name='zhangsan', age='23'}
新对象:People{name='zhangsan', age='23'}
修改后的源对象:People{name='lisi', age='23'}
修改后的新对象:People{name='lisi', age='23'}

因此这时就需要考虑解决办法,如何把源对象的属性给新对象,而且两个对象改变属性时又可以不相互影响?

概念

Java复制对象的实现方式中有个“克隆”的概念,就是复制一个对象的副本,而克隆又分浅克隆和深克隆。

  • 浅克隆:克隆一个新对象,但是属性如果是引用类型对象则用的同一个引动地址指向的对象。
  • 深克隆:克隆一个新对象,包括引用类型的属性内存地址指向的也是新创建的对象。

实现步骤:

  • 实现Clonable接口;
  • 重写clone()方法。
  • 调用clone()方法克隆对象。

浅克隆

1、验证是否为新对象

bean(未重写toString(),用来验证克隆出的对象是否为新的)

public class People implements Cloneable {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //修改权限为:public
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

main

    public static void main(String[] args) throws CloneNotSupportedException {
        People old = new People();
        old.setName("zhangsan");
        old.setAge(23);
        People clone = (People) old.clone();
        System.out.println("源对象:" + old);
        System.out.println("新对象:" + clone);
    }

结果:地址不同,所以clone的新对象和原来的不是同一个

源对象:com.company.bean.People@4554617c
新对象:com.company.bean.People@74a14482

 2、验证引用类型属性是否为新的

Car

public class Car implements Cloneable {
    private String name;
    private String color;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

People

public class People implements Cloneable {
    private String name;
    private int age;
    private Car car;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    //修改权限为:public
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                '}';
    }
}

main

    public static void main(String[] args) throws CloneNotSupportedException {
        People old = new People();
        old.setName("zhangsan");
        old.setAge(23);
        Car car = new Car();
        car.setName("ferrari");
        car.setColor("red");
        old.setCar(car);
        People clone = (People) old.clone();
        System.out.println("源对象:" + old);
        System.out.println("新对象:" + clone);
    }

结果:虽然对象是新的,但是clone的属性还是用一个。

源对象:People{name='zhangsan', age=23, car=com.company.bean.Car@4554617c}
新对象:People{name='zhangsan', age=23, car=com.company.bean.Car@4554617c}

深克隆:重写对象中引用类型属性clone()

Car

public class Car implements Cloneable {
    private String name;
    private String color;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    //重写clone
    @Override
    public  Car clone() throws CloneNotSupportedException {
        return (Car) super.clone();
    }
}

People

public class People implements Cloneable {
    private String name;
    private int age;
    private Car car;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    //重写clone方法
    @Override
    public People clone() throws CloneNotSupportedException {
        People people = (People) super.clone();
        people.car = car.clone();
        return people;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                '}';
    }
}

main

    public static void main(String[] args) throws CloneNotSupportedException {
        People old = new People();
        old.setName("zhangsan");
        old.setAge(23);
        Car car = new Car();
        car.setName("ferrari");
        car.setColor("red");
        old.setCar(car);
        People clone = (People) old.clone();
        System.out.println("源对象:" + old);
        System.out.println("新对象:" + clone);
    }

结果:引用类型属性也是新的

源对象:People{name='zhangsan', age=23, car=com.company.bean.Car@4554617c}
新对象:People{name='zhangsan', age=23, car=com.company.bean.Car@74a14482}

补充:序列化方式实现

Car

public class Car implements Serializable {
    private String name;
    private String color;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

}

People

public class People implements Serializable {
    private String name;
    private int age;
    private Car car;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                '}';
    }
}

main

   public static void main(String[] args) throws IOException, ClassNotFoundException {
        People old = new People();
        old.setName("zhangsan");
        old.setAge(23);
        Car car = new Car();
        car.setName("ferrari");
        car.setColor("red");
        old.setCar(car);
        System.out.println("源对象:" + old);
        //序列化
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(outputStream);
        oos.writeObject(old);
        //反序列化
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(inputStream);
        People clone = (People) ois.readObject();
        System.out.println("新对象:" + clone);
    }

结果:和深克隆一样,对象和引用类型属性的地址都是新的。

源对象:People{name='zhangsan', age=23, car=com.company.bean.Car@4554617c}
新对象:People{name='zhangsan', age=23, car=com.company.bean.Car@2d98a335}

 

原文地址:http://www.cnblogs.com/Bernard94/p/16670090.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性