【发布时间】:2015-09-17 13:23:34
【问题描述】:
我正在学习 Java,因为我需要它作为我的一门大学课程的先决条件。 我来自 C++ 背景,所以理解 OOP 底层的逻辑并不是特别困难。 但这两种语言之间存在一些差异,其中一个我无法弄清楚的是 Java 中存在的对象克隆功能。 这个问题让我想起了 C++ 的复制构造函数,但含义不同。
在 Java 中,没有析构函数,内存由垃圾收集器管理,因此不存在您在 C++ 中遇到的堆内存问题。问题仅限于共享变量。
现在,仔细阅读,我发现对象克隆(与复制构造函数不同)不是 OOP 语言应该提供的功能,因为它创建了另一个跳过构造阶段的对象实例。此外,clone() 无法正确操作 final 字段,并跳过初始化块。克隆背后的相同逻辑是“错误的”,因为“Cloneable”就像一个空接口,仅用于在 Object.clone() 中进行类型检查,以在对象类型不可克隆时引发异常。
所有的克隆机制似乎都依赖于正确分配内存的 Object.clone() 方法。支持 clone() 的类层次结构中的每个子类型都应该调用“super.clone()”,直到调用 Object 来分配所有必要的字段。 但是,如果实现 Cloneable 接口的子类型扩展了不这样做的超类型,会发生什么? 我正在学习“Arnold,Gosling,Holmes”,对克隆的定义行为之一是:“允许子类支持克隆但不公开支持它。这样的类不实现 Cloneable,但如果默认克隆的实现不正确,该类提供了一个受保护的克隆实现,可以正确克隆其字段”。 这样调用super.clone(),最后会碰到超类的受保护的clone()方法,但是这样的方法不能依赖Object.clone(),因为超类本身没有实现Cloneable。使用 new 运算符会出错,因为会创建一个超类的实例,其中缺少一些字段。
那么,在非 Cloneable 类中支持 clone()(使用受保护的方法)真的有用吗? 以及如何解决具有不可克隆超类型的可克隆子类型的问题?
【问题讨论】:
-
Cloneable / clone() 是一个完全被破坏的机制。我建议你避免它。阅读有效的 Java 第 11 条:明智地覆盖克隆。或阅读:artima.com/intv/bloch13.html
-
一些 OOP 课程将教您如何正确实现克隆(使用复制构造函数),并要求您在数据类中这样做。然而,在实践中,支持克隆要么不是太有用,要么不是明智的选择。你可以这样做,但你应该事先考虑是否值得。
标签: java