深拷贝、浅拷贝、克隆 [英] Deep copy, shallow copy, clone

查看:34
本文介绍了深拷贝、浅拷贝、克隆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need clarification on the differences between deep copy, shallow copy, and clone in Java

推荐答案

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

Unfortunately, "shallow copy", "deep copy" and "clone" are all rather ill-defined terms.

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

In the Java context, we first need to make a distinction between "copying a value" and "copying an object".

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.

In short, an assignment of a reference to a variable whose type is a reference type is "copying a value" where the value is the object reference. To copy an object, something needs to use new, either explicitly or under the hood.

现在是对象的浅"复制与深"复制.浅拷贝一般是指只拷贝一个对象的一层,而深拷贝一般是指拷贝多于一层.问题在于决定我们所说的级别是什么意思.考虑一下:

Now for "shallow" versus "deep" copying of objects. Shallow copying generally means copying only one level of an object, while deep copying generally means copying more than one level. The problem is in deciding what we mean by a level. Consider this:

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 字段引用与原始数组相同的数组;例如

The normal interpretation is that a "shallow" copy of eg1 would be a new Example object whose foo equals 1 and whose bar field refers to the same array as in the original; e.g.

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

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

The normal interpretation of a "deep" copy of eg1 would be a new Example object whose foo equals 1 and whose bar field refers to a copy of the original array; e.g.

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

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

(People coming from a C / C++ background might say that a reference assignment produces a shallow copy. However, that's not what we normally mean by shallow copying in the Java context ...)

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

Two more questions / areas of uncertainty exist:

  • 有多深?它是否停留在两个级别?三级?是指连接对象的整个图吗?

  • How deep is deep? Does it stop at two levels? Three levels? Does it mean the whole graph of connected objects?

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

What about encapsulated data types; e.g. a String? A String is actually not just one object. In fact, it is an "object" with some scalar fields, and a reference to an array of characters. However, the array of characters is completely hidden by the API. So, when we talk about copying a String, does it make sense to call it a "shallow" copy or a "deep" copy? Or should we just call it a copy?

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

Finally, clone. Clone is a method that exists on all classes (and arrays) that is generally thought to produce a copy of the target object. However:

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

  • The specification of this method deliberately does not say whether this is a shallow or deep copy (assuming that is a meaningful distinction).

事实上,规范甚至没有特别说明 clone 会产生一个新对象.

In fact, the specification does not even specifically state that clone produces a new object.

这里是 javadoc 说:

创建并返回此对象的副本.副本"的确切含义可能取决于对象的类.一般意图是,对于任何对象x,表达式x.clone() != x 为真,表达式 x.clone().getClass() == x.getClass() 为真,但这些都不是绝对的要求.虽然通常情况下 x.clone().equals(x) 为真,但这不是绝对要求."

"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."

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

Note, that this is saying that at one extreme the clone might be the target object, and at the other extreme the clone might not equal the original. And this assumes that clone is even supported.

简而言之,对于每个 Java 类,克隆可能意味着不同的东西.

In short, clone potentially means something different for every Java class.

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

Some people argue (as @supercat does in comments) that the Java clone() method is broken. But I think the correct conclusion is that the concept of clone is broken in the context of OO. AFAIK, it is impossible to develop a unified model of cloning that is consistent and usable across all object types.

这篇关于深拷贝、浅拷贝、克隆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆