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

相關文章
相關標籤/搜索