- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我需要澄清一下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 expressionx.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is typically the case thatx.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/
免责声明 这篇文章是关于术语“浅拷贝”和“深拷贝”的正确用法,特别是在谈论复制一个不包含任何引用的对象时。这个问题并不意味着(也不应该)基于意见,除非真的没有关于这个话题的共识。我已将此问题标记为 C
我有这个功能 int getrelation(string name, RELATION& output){ bool found=0; int index=0;
与 why should I make a copy of a data frame in pandas 有关 我注意到在流行的backtesting图书馆, def __init__(self, d
我的问题很基础,但我想 100% 理解所有内容。 SO中的很多问题都引用了我的帖子,但我没有找到满意的答案。 我们知道java中的枚举是引用类型。让我们考虑以下片段: public static cl
请引用这个 fiddle 的问题。 http://jsfiddle.net/AQR55/ 1)为什么附加到隔离范围属性的 watch - 双向绑定(bind)到父属性,不会在更改父范围属性时触发。 在
我想使用 UP3 来完成一项非常具体的任务,我应该能够使用 API 来实现该任务。我想了解是否可以编写以下应用程序。 基于https://jawbone.com/support/articles/00
如何在辅助方法中传递上下文并提取数据? 请参阅以下代码片段: import AppContext from '../../context/AppContext' import extractDatta
我正在尝试使用 simple-git 创建浅克隆。我正在尝试创建与此命令等效的命令:git clone --depth 1 https://github.com/steveukx/git-js.git
我是一名优秀的程序员,十分优秀!