【问题标题】:cloing object which has reference to another mutable object in java克隆引用了java中另一个可变对象的对象
【发布时间】:2014-03-08 13:07:05
【问题描述】:

我正在学习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 对象的所有内容复制到一个新对象中,这样我就可以安全地修改新对象而不影响原始对象。

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

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的原因是什么 对象。

【问题讨论】:

  • 你永远不会在你的客户对象上调用.clone()
  • 抱歉,我在从文本编辑器复制时忘记添加克隆行。修改了我的问题。所以当我执行程序时克隆方法就在那里,但是它没有帮助。

标签: java clone


【解决方案1】:

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

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

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

您可以使用Cloneable 接口走传统路线并按原样创建它,但是当您可以使用可用的构造函数简单地创建对象的新实例时,没有真正需要这样做,这将立即切断两个对象之间的所有关系(除了具有相等的值)。

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

如果您正在处理多个层(继承),那么您必须记住事先调用 super.clone() 并实现您的 clone() 方法。

它是如何工作的?很简单,考虑下面的sn-p:

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

【讨论】:

  • 感谢您的解释。现在我明白了克隆方法没有正确实现的事实。
猜你喜欢
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多