微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java:为什么字符串在深拷贝和浅拷贝中很特殊?

如何解决Java:为什么字符串在深拷贝和浅拷贝中很特殊?

这几天我在学习 Java 的 clone 方法。我了解到 clone 使用浅拷贝。如果我想实现一个对象的深拷贝,那么我应该遵循this website

中的以下原则

无需单独复制原语。 原始类中的所有成员类都应该支持克隆,并且在上下文中原始类的clone方法中应该对所有成员类调用super.clone()。

在我的理解中,String在Java中是一种引用,为了更好地表达我的观点,代码如下:

// User.java
public class User implements Cloneable{
    private String name;

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

    // Getter(),setter() and toString() are omitted here
}

以下代码为测试代码

User user = new User();
user.setName("one");

User clone = (User)user.clone();
clone.setName("two");

System.out.println(user.getName());     // I think it should print "two",but actually "one"

因此,在我的示例中,我似乎创建了 User(do I?)

的深层副本

以下是我对Java内存的理解:

①表示我创建了一个副本,②是String的变化。

所以如果我的图片是正确的,它应该打印“两个”,对吗?

我知道 java 中的 String 是不可变的,我认为这可能是发生这种情况的原因,但我不知道这是怎么发生的以及发生这种情况的原因。 >


根据@Jesper的图片,我创建了一张新图片来更具体地解释我的问题。

和演示代码

public class Employee implements Cloneable {

    private int employeeId;
    private String employeeName;
    private Department department;

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

    // Getter(),setter() and toString() are omitted here
}
public class Department{
    private int id;
    private String name;

    // Getter(),setter() and toString() are omitted here
}

测试代码

Department hr = new Department(1,"Human Resource");
Employee original = new Employee(1,"Admin",hr);
Employee cloned = (Employee) original.clone();
cloned.getDepartment().setName("Finance");
System.out.println(original.getDepartment().getName());  //print Finance

还有图:

红色部分是关键。如果它是 java.lang.String 对象,它将创建一个新对象(如上所示从“一”到“二”),但如果它是另一个类对象(这里是 Department 类)那么它似乎只有一个对象(而不是创建一个),所以我的问题是为什么 String 在深拷贝和浅拷贝中是 special ?这与 String 不变性有关吗?

提前致谢!

解决方法

你从这种情况开始:

enter image description here

然后您克隆 User 对象。您现在有两个 User 对象;变量 userclone 指的是这两个对象。请注意,它们的 name 成员变量都指向同一个 String 对象,内容为 "one"

enter image description here

然后您在 setName("two") 上调用 clone,这将更改第二个 name 对象的 User 成员变量以引用不同的 String 对象,内容为 "two"

enter image description here

注意变量 user 仍然指向 User 对象,它的 name 成员变量指向 "one",所以当你 System.out.println(user.getName());one

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?