gpt4 book ai didi

java - 深拷贝、浅拷贝、克隆

转载 作者:IT老高 更新时间:2023-10-28 11:51:54 26 4
gpt4 key购买 nike

我需要澄清一下Java中深拷贝、浅拷贝和克隆之间的区别

最佳答案

不幸的是,“浅拷贝”、“深拷贝”和“克隆”都是定义不明确的术语。


在Java上下文中,我们首先需要区分“复制值”和“复制对象”。

int a = 1;
int b = a; // copying a value
int[] s = new int[]{42};
int[] t = s; // copying a value (the object reference for the array above)

StringBuffer sb = new StringBuffer("Hi mom");
// copying an object.
StringBuffer sb2 = new StringBuffer(sb);

简而言之,对类型为引用类型的变量的引用赋值是“复制值”,其中该值是对象引用。要复制一个对象,需要使用 new,无论是显式的还是底层的。


现在针对对象的“浅”与“深”复制。浅拷贝一般是指只拷贝一个对象的一层,而深拷贝一般是指拷贝多于一层。问题在于确定我们所说的水平是什么意思。考虑一下:

public class Example {
public int foo;
public int[] bar;
public Example() { };
public Example(int foo, int[] bar) { this.foo = foo; this.bar = bar; };
}

Example eg1 = new Example(1, new int[]{1, 2});
Example eg2 = ...

通常的解释是 eg1 的“浅”副本将是一个新的 Example 对象,其 foo 等于 1 并且其 bar 字段引用与原始数组相同的数组;例如

Example eg2 = new Example(eg1.foo, eg1.bar);

eg1 的“深层”副本的正常解释是一个新的 Example 对象,其 foo 等于 1 并且其 bar 字段是指原始数组的副本;例如

Example eg2 = new Example(eg1.foo, Arrays.copy(eg1.bar));

(来自 C/C++ 背景的人可能说引用赋值会产生浅拷贝。然而,这不是我们通常在 Java 上下文中所说的浅拷贝......)

还有两个问题/不确定的领域:

  • 有多深?是不是停在两个层面?三级?是指连接对象的整个图吗?

  • 封装的数据类型呢?例如一个字符串? String 实际上不仅仅是一个对象。事实上,它是一个带有一些标量字段的“对象”,以及对字符数组的引用。但是,API 完全隐藏了字符数组。那么,当我们谈论复制字符串时,将其称为“浅”副本还是“深”副本有意义吗?还是我们应该称之为副本?


最后,克隆。克隆是一种存在于所有类(和数组)上的方法,通常被认为会生成目标对象的副本。然而:

  • 此方法的规范故意没有说明这是浅拷贝还是深拷贝(假设这是有意义的区别)。

  • 事实上,规范甚至没有明确说明克隆会产生一个新对象。

这里是 the javadoc说:

"Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression x.clone() != x will be true, and that the expression x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements. While it is typically the case that x.clone().equals(x) will be true, this is not an absolute requirement."

注意,这是说在一个极端,克隆可能是目标对象,而在另一个极端,克隆可能不等于原始对象。这假设甚至支持克隆。

简而言之,克隆对于每个 Java 类都有不同的含义。


有些人争论(就像@supercat 在评论中所做的那样)Java clone() 方法被破坏了。但我认为正确的结论是克隆的概念在OO的上下文中被打破了。 AFAIK,不可能开发出一个统一的克隆模型,该模型在所有对象类型中都是一致且可用的。

关于java - 深拷贝、浅拷贝、克隆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6182565/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com