Java中clone()方法浅析

1、Java中的赋值

java中对象的赋值是经过对象的引用的形式进行赋值。java

1.1 关于赋值的实现

  • 建立Person类
public class Person {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' + ", age=" + age + '}'; } } 复制代码
  • 测试赋值
@Test
public void testSimpleDemo(){
    Person p1 = new Person();
    p1.setName("tom");
    p1.setAge(21);

    Person p2 = p1;

    System.out.println(p1); //Person{name='tom', age=21}
    System.out.println(p2); //Person{name='tom', age=21}
    System.out.println(p1 == p2);   //true

}
复制代码

2、Java中clone的实现

  • 实现clone要让实体类实现Cloneable接口
  • 再重写接口中的clone方法

实现Cloneable接口

public class Person implements Cloneable {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' + ", age=" + age + '}'; } } 复制代码

测试

@Test
public void testShallowClone() throws CloneNotSupportedException {
    Person p1 = new Person();
    p1.setName("tom");
    p1.setAge(21);

    Person p2 = (Person) p1.clone();
    System.out.println(p1); //Person{name='tom', age=21}
    System.out.println(p2); //Person{name='tom', age=21}

    System.out.println(p1 == p2);   //false
}
复制代码

注意:若是实体类中添加了引用类型的对象bash

  • 建立Address类
public class Address {

    private String type;
    private String name;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Address{" +
                "type='" + type + '\'' + ", name='" + name + '\'' + '}'; } } 复制代码
  • 添加Address属性
public class Person implements Cloneable {

    private String name;
    private Integer age;
    private Address address;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' + ", age=" + age + ", address=" + address + '}'; } } 复制代码
  • 测试
@Test
public void testShallowClone() throws CloneNotSupportedException {
    Address address = new Address();
    address.setType("home");
    address.setName("北京");

    Person p1 = new Person();
    p1.setName("tom");
    p1.setAge(21);
    p1.setAddress(address);

    Person p2 = (Person) p1.clone();
    p2.getAddress().setType("office");

    System.out.println(p1); //Person{name='tom', age=21, address=Address{type='office', name='北京'}}
    System.out.println(p2); //Person{name='tom', age=21, address=Address{type='office', name='北京'}}

    System.out.println(p1 == p2);   //false
}
复制代码

这里就发现了问题,我只在p2对象中将type属性修改成office,但是p1也跟着改变了,该如何解决呢?ide

3、clone问题的解决

要解决问题首先要知道深拷贝和浅拷贝是什么学习

  • 浅拷贝:只是拷贝了对象的实例,可是对象中的属性仍是会指向原有的对象。
  • 深拷贝:在浅拷贝的基础上,再将对象中的属性额外的复制一份,对象中的属性会指向新的对象。

若是只是实现基本类型的赋值,只须要实现Cloneable接口便可,可是若是是引用类型的话就须要将这些对象都实现Cloneable接口并重写clone方法测试

步骤:ui

  • Address类实现Cloneable接口,并重写clone方法
  • Person类中重写clone方法
public class Person implements Cloneable {

    private String name;
    private Integer age;
    private Address address;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        Address address = ((Person) obj).getAddress();
        ((Person) obj).setAddress((Address) address.clone());
        return obj;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' + ", age=" + age + ", address=" + address + '}'; } } 复制代码
  • 测试
@Test
public void testShallowClone() throws CloneNotSupportedException {
    Address address = new Address();
    address.setType("home");
    address.setName("北京");

    Person p1 = new Person();
    p1.setName("tom");
    p1.setAge(21);
    p1.setAddress(address);

    Person p2 = (Person) p1.clone();
    p2.getAddress().setType("office");

    System.out.println(p1); //Person{name='tom', age=21, address=Address{type='home', name='北京'}}
    System.out.println(p2); //Person{name='tom', age=21, address=Address{type='office', name='北京'}}

    System.out.println(p1 == p2);   //false
}
复制代码

这样便解决了clone引用类型的问题this

做者学习自 blog.csdn.net/qq_33314107… 文中若有错误望加以指正spa

相关文章
相关标签/搜索