我正在学习Java,因为我需要它作为我大学课程的一个要求。 我来自C ++背景,因此理解OOP背后的逻辑并不是特别困难。 但是这两种语言之间存在一些差异,而我无法弄清楚的是Java中存在的对象克隆功能。 这个问题让我想起了C ++的复制构造函数,但其含义却不同。
在Java中,没有析构函数,内存由垃圾收集器管理,因此在C ++中不存在堆内存问题。问题仅限于共享变量。
现在,阅读,我发现对象克隆(与复制构造函数不同)不是OOP语言应该提供的功能,因为它创建了跳过构造阶段的对象的另一个实例。此外,clone()无法正确操作最终字段,并跳过初始化块。克隆背后的相同逻辑是“错误的”,因为“Cloneable”就像一个空接口,只提供在Object.clone()中进行类型检查,如果对象的类型不是Cloneable则引发异常。
所有克隆机制似乎都依赖于Object.clone()方法,该方法可以正确分配内存。支持clone()的类层次结构中的每个子类型都应该调用“super.clone()”,直到调用Object 1来分配所有必需的字段。 但是,如果实现Cloneable接口的子类型扩展超类型而不这样做会发生什么? 我正在研究“Arnold,Gosling,Holmes”,并且克隆的定义行为之一是:“允许子类支持克隆但不公开支持它。这样的类不实现Cloneable,但是如果默认clone的实现不正确,该类提供了一个正确克隆其字段的受保护克隆实现“。 这样,调用super.clone(),最终我们会碰到超类的受保护的clone()方法,但是这样的方法不能依赖于Object.clone(),因为超类本身并没有实现Cloneable。使用new运算符将是一个错误,因为将创建一个超类的实例,其中包含一些缺少的字段。
那么,在非Cloneable类中支持clone()(带有受保护的方法)真的很有用吗? 如何解决具有非Cloneable超类型的Cloneable子类型的问题?
答案 0 :(得分:2)
但是,如果实现
Cloneable
接口的子类型扩展超类型而不这样做会发生什么?
如果只是implements Cloneable
而没有实际覆盖clone()
(是的,这也是可能的!),那么就不会造成任何伤害。
如果它覆盖clone()
并返回一个未从super.clone()
检索的实例,那么它已经破坏了它的所有子类。这是clone()
公认的陷阱之一(在Effective Java中有所介绍)。
如何解决具有非Cloneable超类型的Cloneable子类型的问题?
如上所述,只要不可克隆的超类型不会覆盖clone()
(是的,那是又一种的可能性!)或者覆盖它,这不是问题,但是以合规的方式。
答案 1 :(得分:0)
如何解决具有非Cloneable超类型的Cloneable子类型的问题?
实际上这不是问题。考虑类Object
:这是一种非Cloneable类型,并用作任何Cloneable
类型的超类型。您可以创建任何类型T的Cloneable
子类型。唯一重要的是:对于该类型T(及其超类型)正确实现的“克隆”操作。对于类Object
,这将返回原始对象的字段,浅层副本,与原始对象具有相同的类。
即。并非子类的超类线程中的每个类型都必须实现Cloneable
。
...在非Cloneable类中支持clone()(带有受保护的方法)真的很有用吗?
是。例如。请参阅(非克隆)类Object
中的clone()的默认实现。