【问题标题】:Cloning in Java [duplicate]Java中的克隆[重复]
【发布时间】:2018-10-23 11:11:10
【问题描述】:
class Person implements Cloneable {

    String firstName;

    public String getFirstName() {
        return firstName;
     }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public Person clone() throws CloneNotSupportedException {
            return (Person) super.clone();
        }
   }

    Person p1 = new Person();
    p1.setFirstName("P1 Sara");

    Person p3 = new Person();
    try {
        p3 = (Person) p1.clone();
    } catch (CloneNotSupportedException e) {
    }

    p3.setFirstName("cloned Sara");
    System.out.println("P3 : " + p3.getFirstName());
    System.out.println("P1: " + p1.getFirstName());

我读过 clone() 方法实际上是一个浅拷贝。 所以,我假设当 P3 中某个字段的值发生变化时,P1 中的值也会发生变化。 但是,那并没有发生。 我在这里想念什么?

【问题讨论】:

  • 浅拷贝意味着它们有单独的字段,但这些字段引用相同的实例。这就像您将朋友的电话号码复制到新手机上:您只有两个电话号码副本,但他们拨打的是同一个电话。
  • String 是不可变类型。这意味着当您想要复制或克隆它时,您有一个字符串的 new 实例,其中包含复制的值。如果更改克隆的字符串,它不会影响原始字符串。
  • @AndyTurner 因此,在这种情况下,P3 是 P1 的克隆。他们不应该都引用同一个名字字段吗?
  • @Sara 继续电话类比:您已将电话号码复制到另一部电话上。他们在两个地方存储相同的东西;两部手机没有将内容放入同一个电话簿。如果你在一个地方更新它,它不会在另一个地方更新。
  • @KarelG 不完全是:克隆对象不会克隆字符串:它们都共享相同的实例,但是如果 - 克隆后 - 您更新原始字符串,它只会在克隆时指向另一个字符串将继续指向初始字符串值。

标签: java clone cloneable


【解决方案1】:

clone() 方法实际上是浅拷贝。
以下是您的示例中发生的情况:

  1. person1 有对名称的引用。我们将此引用称为 A。引用 A 指向堆内存中的某个位置。
  2. 将 person1 复制到 person3 后,person3 中的名称引用(我们称之为引用 B)指向堆内存中的相同位置。 但它不是同一个引用。这是 2 个不同的引用指向堆内存中的同一位置
  3. 当您调用p3.setFirstName("cloned Sara") 时,引用B 会更新为指向堆内存中的另一个位置。没有理由改变引用 A 指向的位置的值。

【讨论】:

  • 哦,好的。我正在尝试克隆示例。我应该如何修改 Person 类以真正反映浅拷贝?即,P3 的变化反映在 P1 中,反之亦然?
  • 您可以将不可变的String 类替换为可变类,例如StringBuilderStringBuffer,并让setter 更改可变对象内的值,而不是使用operator = 将引用指向其他地方。
猜你喜欢
  • 2012-02-13
  • 2014-06-09
  • 2019-05-09
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
  • 2020-03-04
  • 2015-08-27
  • 2010-09-29
相关资源
最近更新 更多