Java 为什么 Object clone() 方法仅适用于实现 Cloneable 接口的类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18240037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why Object clone() method available only to classes that implement Cloneable interface?
提问by Don_Quijote
I know that clone()
is a protected method, but "protected" means that it is accessible for all subclasses of particular class.
我知道这clone()
是一个受保护的方法,但“受保护”意味着它可以被特定类的所有子类访问。
Any Java class is a subclass of Object
, so what is the reason for the protected method here?
任何 Java 类都是 的子类Object
,那么这里的受保护方法的原因是什么?
And why can we call clone()
only on classes that implement the Cloneable
interface?
I can't understand how it connects to the fact that clone()
in Object
is declared as protected.
为什么我们clone()
只能调用实现Cloneable
接口的类?我无法理解它如何与clone()
inObject
被声明为受保护的事实相联系。
采纳答案by Cephalopod
Object's clone() method is quite special, as it always returns an instance of the current class that has all fields copied (even final). I don't think its possible to reproduce this with plain Java code, not even with reflection.
Object 的 clone() 方法非常特殊,因为它总是返回当前类的一个实例,该实例复制了所有字段(甚至是 final)。我认为用普通的 Java 代码不可能重现这个,即使是用反射也不可能。
Because of this, it must be made available to all classes, but since it should not be callable from the outside by default because you don't want everything to be cloneable, it must be protected.
因此,它必须可供所有类使用,但由于您不希望所有类都可克隆,因此默认情况下不应从外部调用它,因此必须对其进行保护。
As an additional check, clone
checks that the class implements Cloneable
, only to ensure you don't clone non-cloneables by accident.
作为额外的检查,clone
检查类是否实现了Cloneable
,只是为了确保您不会意外克隆不可克隆的对象。
All in all, cloning is somewhat broken because it doesn't work when you need to deep-copy final fields. I recommend you implement instance copying manually, following this pattern.
总而言之,克隆有点被破坏,因为当您需要深度复制最终字段时它不起作用。我建议您按照此模式手动实现实例复制。
public class Base {
/** one or more public constructors */
public Base() { ... }
/** copy-constructor */
protected Base(Base src) { /* copy or deep-copy the state */ }
public Base copy() { return new Base(this); }
}
public class Derived extends Base {
/** one or more public constructors */
public Derived() { ... }
/** copy-constructor */
protected Derived(Derived src) {
super(src);
/* copy or deep-copy the state */
}
@Override
public Derived copy() { return new Derived(this); }
}
回答by Suresh Atta
http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html
http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class. Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See Object.clone() for details on overriding this method.
Note that this interface does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.
一个类实现了 Cloneable 接口,以向 Object.clone() 方法指示该方法制作该类实例的字段对字段副本是合法的。在未实现 Cloneable 接口的实例上调用 Object 的 clone 方法会导致抛出异常 CloneNotSupportedException。
按照惯例,实现此接口的类应该使用公共方法覆盖 Object.clone(受保护)。有关覆盖此方法的详细信息,请参阅 Object.clone()。
请注意,此接口不包含 clone 方法。因此,不能仅仅凭借对象实现了这个接口就克隆一个对象。即使以反射方式调用 clone 方法,也不能保证它会成功。
Coming to your question even though Object has protected method clone
Object
does not implement Cloneable
,But the object being called the clone()
method must implement Cloneable interface
.
即使 Object 具有 protected 方法clone
Object
没有实现Cloneable
,但您的问题也没有实现,但是被调用该clone()
方法的对象必须实现 Cloneable interface
。
回答by Ankit Zalani
Cloneable is an interface and in order to clone a reference to an abstract base class, either the base class must have a clone() method, or one of its parents must have a publicly accessible clone() method. Cloneable just acts as a marker interface.
Cloneable 是一个接口,为了克隆对抽象基类的引用,基类必须具有 clone() 方法,或者其父类之一必须具有可公开访问的 clone() 方法。Cloneable 只是作为一个标记界面。
Please refer to:
请参阅:
回答by user207421
Because that's the way they designed it. There's a statement somewhere in the Bug Parade that the original reasons for the design are 'lost in the mists of time', but I remember a discussion by Sun in the 1990s that said the design gave four possible behaviors.
因为那是他们设计的方式。在 Bug Parade 的某处有一个声明,说设计的最初原因是“迷失在时间的迷雾中”,但我记得 Sun 在 1990 年代的一次讨论中说该设计给出了四种可能的行为。
Cannot remember the details :-| But you can work it out:
不记得细节了:-| 但你可以解决:
- Do nothing. Class cannot be cloned and
clone()
method is inaccessible except to derived classes. - Implement
Cloneable:
Class can be cloned butclone()
method is inaccessible except to derived classes. - Implement
Cloneable
and provide your ownclone()
method: as (2) but the possibility exists to makeclone()
public and also now to return the correct type. - Derived from a class that does (2) or (3), implement
clone()
, and throwNotCloneableException:
you are back to 1.
- 没做什么。类不能被克隆,
clone()
方法是不可访问的,除非派生类。 - 实现
Cloneable:
类可以被克隆,但clone()
除了派生类之外,方法是不可访问的。 - 实现
Cloneable
并提供您自己的clone()
方法:如 (2),但存在clone()
公开并现在返回正确类型的可能性。 - 派生自执行 (2) 或 (3)、实现
clone()
和抛出的类,NotCloneableException:
您将返回到 1。
Putting clone()
into the interface would have lost some of that.
把clone()
插入接口就已经失去了一些这一点。
回答by Bill Horvath
Cloneable is a marker interface. The clone() method isn't defined by the Cloneable interface.
Cloneable 是一个标记界面。clone() 方法不是由 Cloneable 接口定义的。
The clone method in the Object class is protected to prevent a client class from calling it - Only subclasses can call or override clone, and doing so is a bad idea.
Object 类中的 clone 方法受到保护,以防止客户端类调用它 - 只有子类可以调用或覆盖 clone,这样做是一个坏主意。
回答by supercat
The default implementation of Object.clone()
is the only way (other than perhaps Reflection) via which a base-type method in an object can produce a new object of that object's same type. On the other hand, there are many classes for which it would be impossible for a derived class to implement a working clone
method which would not violate the base-class invariants. It was desired that such derived classes not be allowed to call clone
and receive an object that couldn't possibly be usable.
的默认实现Object.clone()
是对象中的基类型方法可以生成该对象相同类型的新对象的唯一方法(可能除了反射)。另一方面,有许多类的派生类不可能实现clone
不违反基类不变量的工作方法。人们希望不允许这样的派生类调用clone
和接收不可能使用的对象。
In retrospect, the proper thing to have done might have been to define a system CloneableObject
which inherits from Object
which includes a protected memberwiseclone
method (that works like Object.clone()
does now) and nothing else, and have all classes which are going to be cloneable inherit from that as their base type. That type could use then some special magic within its clone()
method that was unavailable to other types. Instead, however, the system uses the existence of the Cloneable
interface to decide whether objects should be allowed to use the base-level clone()
method. Not a great design, but it is what it is. Hard to say whether that's better or worse than the .NET approach of allowing nearly all derived classes to call MemberwiseClone
whether or not there would be any way a derived class could do so without yielding a broken object.
回想起来,正确的做法可能是定义一个系统CloneableObject
,该系统继承自Object
该系统,其中包括一个受保护的memberwiseclone
方法(就像Object.clone()
现在一样),没有其他任何东西,并且让所有可克隆的类继承自该方法作为它们的基型。该类型可以在其clone()
方法中使用一些其他类型无法使用的特殊魔法。然而,系统使用Cloneable
接口的存在来决定是否应该允许对象使用基本级别的clone()
方法。不是一个伟大的设计,但它就是它。很难说这比允许几乎所有派生类调用的 .NET 方法好还是坏MemberwiseClone
派生类是否可以在不产生损坏对象的情况下这样做。