克隆对象,它引用了java中的另一个可变对象

时间:2014-03-08 13:07:06

标签: java clone

我正在学习java。这是我编写的代码,作为理解如何在java中克隆对象的一部分...

Class Address {
 String city;
 String state;
}

class Customer implements Cloneable {
  String name;
  Address address;

  public Customer(String name, String city, String state) {
    this.name = name;
    address = new Address();
    address.city = city;
    address.state = state;
  }

  public Object clone() {
    Customer coned = null;
    try {
      cloned = super.cloned();
      return cloned; 
    } catch(CloneNotSupportedException e) {
      return null;
    }
  }
}

这里我想克隆一个Customer对象,如下所示 -

Customer customer = new Customer("john", "acity", "astate");
Customer newCustomer = (Customer) customer.clone();
newCustomer.address.city = "bcity";

这就是问题所在。一旦我为city设置了新值,它实际上也会更新原始对象。我的目标是将Customer对象的所有内容复制到一个新对象,以便我可以安全地修改新对象而不会影响原始对象。

为此,我修改了clone类的Customer方法 -

public Object clone() {
 Customer coned = null;
 try {
  cloned = super.cloned();
  clone.address = (Address) address.clone();
  return cloned; 
 } catch(CloneNotSupportedException e) {
   return null;
 }
}

这是更新的地址类 -

class Address {
 String city;
 String state;
 public Object clone() 
  throws CloneNotSupportedException
 {
   return super.clone(); 
 }
}

任何人都可以帮助我了解错误克隆的原因是什么address 对象

1 个答案:

答案 0 :(得分:1)

好的,首先:请将IDE中的确切代码复制粘贴到您的问题中。你的代码中仍有一些问题会阻止它编译,确实复制它比输入它要容易得多吗?

你遇到的关键问题很简单:你什么都不做。您唯一要做的就是在整个层次结构中调用super.clone(),这最终会导致Object.clone()被调用(这对您的自定义类中的字段没有任何影响)。

解决方案?在clone()方法中添加实际的克隆逻辑。

您可以使用Cloneable接口继续传统路由并创建它,但是当您可以使用可用的构造函数创建对象的新实例时,实际上并不需要这样做,这将立即切断两个对象之间的每个关系(除了具有相等的值)。

您必须记住的是为每个引用类型创建一个新实例,该实例作为当前图层中的字段保存。

如果您正在处理多个图层(继承),那么您必须记得事先致电super.clone()并实施clone()方法。

它是如何工作的?很简单,请考虑以下代码段:

public class Main {
    public static void main(String[] args) {
        Customer jack = new Customer("Jack", "Jackson");
        jack.setBalance(9001);

        Customer john = jack.clone();
        john.setBalance(1337);

        System.out.println("Jack's balance (name = " + jack.getFirstname()
                + "): " + jack.getBalance());
        System.out.println("John's balance (name = " + john.getFirstname()
                + "): " + john.getBalance());
    }
}

class Customer {
    private String firstname, lastname;
    private int balance;

    public Customer(String firstname, String lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
        balance = 500;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int b) {
        this.balance = b;
    }

    protected Customer clone() {
        Customer newCustomer = new Customer(getFirstname(), getLastname());
        newCustomer.setBalance(getBalance());
        return newCustomer;
    };
}

此输出结果如下:

  

杰克的余额(姓名=杰克):9001
  约翰的余额(姓名=杰克):1337