为什么在 java.lang.Object 中保护了 clone() 方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1138769/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:10:47  来源:igfitidea点击:

Why is the clone() method protected in java.lang.Object?

javaoopclone

提问by Alex N.

What is the specific reason that clone()is defined as protected in java.lang.Object?

clone()被定义为 protected的具体原因是java.lang.Object什么?

采纳答案by oxbow_lakes

The fact that clone is protected is extremely dubious - as is the fact that the clonemethod is not declared in the Cloneableinterface.

克隆受保护的事实非常可疑 -clone方法未在Cloneable接口中声明的事实也是如此。

It makes the method pretty useless for taking copies of data because you cannot say:

它使该方法对于获取数据副本毫无用处,因为您不能说

if(a instanceof Cloneable) {
    copy = ((Cloneable) a).clone();
}

I think that the design of Cloneableis now largely regarded as a mistake(citation below). I would normally want to be able to make implementations of an interface Cloneablebut not necessarily make the interface Cloneable(similar to the use of Serializable). This cannot be done without reflection:

我认为,设计Cloneable是现在很大程度上被视为一个错误(以下引文)。我通常希望能够实现接口,Cloneable不一定要创建接口Cloneable(类似于使用Serializable)。没有反思就无法做到这一点:

ISomething i = ...
if (i instanceof Cloneable) {
   //DAMN! I Need to know about ISomethingImpl! Unless...
   copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}

Citation From Josh Bloch's Effective Java:
"The Cloneable interface was intended as a mixin interface for objects to advertise that they permit cloning. Unfortunately it fails to serve this purpose ... This is a highly atypical use of interfaces and not one to be emulated ... In order for implementing the interface to have any effect on a class, it and all of its superclasses must obey a fairly complex, unenforceable and largely undocumented protocol"

来自Josh Bloch 的 Effective Java 的引用:
“Cloneable 接口旨在作为对象的混合接口,用于宣传它们允许克隆。不幸的是,它无法达到此目的......这是一种非常非典型的接口使用,而不是可以模拟的...为了实现接口对一个类产生任何影响,它和它的所有超类必须遵守一个相当复杂、无法执行且大部分未记录的协议

回答by Andrew Hare

cloneis protected because it is something that ought to be overridden so that it is specific to the current class. While it would be possible to create a public clonemethod that would clone any object at all this would not be as good as a method written specifically for the class that needs it.

clone受保护是因为它应该被覆盖,以便它特定于当前类。虽然可以创建一个clone可以克隆任何对象的公共方法,但不如专门为需要它的类编写的方法好。

回答by Silfverstrom

The Clone method can't be directly used on any object, which is why it is intended to be overriden by the subclass.

Clone 方法不能直接在任何对象上使用,这就是为什么它要被子类覆盖的原因。

Of course it could be public and just throw an appropriate exception when cloning is not possible, but i think that would be misleading.

当然,它可能是公开的,并且在无法进行克隆时只是抛出一个适当的异常,但我认为这会产生误导。

The way clone is implemented right now makes you think about why you want to use clone, and how you want your object to be cloned.

现在克隆的实现方式让您思考为什么要使用克隆,以及您希望如何克隆对象。

回答by Pavel Minaev

It is protected because the default implementation does a shallow memberwise copy of all fields (including private), circumventing constructor. This is not something an object might be designed to handle in the first place (for example, it might keep track of created object instances in a shared list, or something similar).

它是受保护的,因为默认实现对所有字段(包括私有)进行了浅成员复制,绕过了构造函数。这不是一个对象最初可能被设计用来处理的事情(例如,它可能会跟踪共享列表中创建的对象实例,或类似的东西)。

For the same reason, the default implementation of clone()will throw if the object it's called on doesn't implement Cloneable. It's a potentially unsafe operation with far-reaching consequences, and therefore author of the class must explicitly opt-in.

出于同样的原因,clone()如果调用它的对象没有实现,则默认实现将抛出Cloneable。这是一个具有深远影响的潜在不安全操作,因此该类的作者必须明确选择加入。

回答by Janusz

From the javadoc of cloneable.

来自可克隆的javadoc。

* By convention, classes that implement this interface (cloneable) should override 
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.

* Note that this interface does <i>not</i> contain the <tt>clone</tt> 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.

So you could call clone on every object but this would give you most of the time not the results you want or an exception. But is only encouraged if you implement cloneable.

所以你可以在每个对象上调用 clone ,但这在大多数情况下会给你而不是你想要的结果或异常。但只有在您实现可克隆时才被鼓励。

回答by Bill K

The Clonable interface is just a marker saying the class can support clone. The method is protected because you shouldn't call it on object, you can (and should) override it as public.

Clonable 接口只是一个标记,表明该类可以支持克隆。该方法是受保护的,因为您不应该在对象上调用它,您可以(并且应该)将其覆盖为 public。

From Sun:

来自太阳:

In class Object, the clone() method is declared protected. If all you do is implement Cloneable, only subclasses and members of the same package will be able to invoke clone() on the object. To enable any class in any package to access the clone() method, you'll have to override it and declare it public, as is done below. (When you override a method, you can make it less private, but not more private. Here, the protected clone() method in Object is being overridden as a public method.)

在 Object 类中,clone() 方法被声明为受保护的。如果您所做的只是实现 Cloneable,则只有同一包的子类和成员才能对对象调用 clone()。要使任何包中的任何类能够访问 clone() 方法,您必须覆盖它并将其声明为 public,如下所示。(当你重写一个方法时,你可以让它不那么私有,但不能让它更私有。这里,Object 中受保护的 clone() 方法被重写为公共方法。)

回答by Bill K

Yes, same problem that I met. But I solve it by implementing this code

是的,我遇到了同样的问题。但我通过实现这段代码来解决它

public class Side implements Cloneable {
    public Side clone() {

        Side side = null;
        try {
            side = (Side) super.clone();
        } catch (CloneNotSupportedException e) {
            System.err.println(e);
        }
        return side;
    }
}

Just as the before someone said.

就像之前有人说的那样。

回答by Victor

Again, Java JDK framework shows brilliant thinking:

再次,Java JDK 框架展示了绝妙的想法:

Cloneable interface does not contain a "public T clone();" method because it acts more like an attribute (eg. Serializable) which allows an instance it to be cloned.

可克隆接口不包含“public T clone();” 方法,因为它更像是一个属性(例如可序列化),它允许克隆它的实例。

There is nothing wrong with this design because:

这种设计没有任何问题,因为:

  1. Object.clone() will not do what you want with your custom-defined class.

  2. If you have Myclass implements Cloneable => you overwrite clone() with "public MyClass clone()"

  3. If you have MyInterface extends Cloneable and some MyClasses implementing MyInterface: simply define "public MyInterface clone();" in the interface and every method using MyInterface objects will be able to clone them, no matter their MyClass-class.

  1. Object.clone() 不会对自定义类执行您想要的操作。

  2. 如果你有 Myclass 实现 Cloneable => 你用“public MyClass clone()”覆盖 clone()

  3. 如果你有 MyInterface 扩展 Cloneable 和一些实现 MyInterface 的 MyClasses:只需定义“public MyInterface clone();” 在接口中,并且每个使用 MyInterface 对象的方法都可以克隆它们,无论它们的 MyClass 类如何。

回答by mark

Well, also the sun developers are only human, and they did indeed make huge mistake to implement the clone method as protected, the same mistake as they implemented a non-functioning clone method in ArrayList! So, in general, there exist a much deeper misunderstanding of even experienced Java programmers about the clone method.

好吧,sun 开发人员也只是人类,他们确实犯了很大的错误,将 clone 方法实现为 protected,与他们在 ArrayList 中实现了一个不起作用的 clone 方法相同的错误!因此,总的来说,即使是有经验的 Java 程序员,对 clone 方法也存在更深层次的误解。

However, I've recently found a fast and easy solution to copy any object with all its content, no matter how it is built and what it contains, see my answer here: Bug in using Object.clone()

但是,我最近找到了一种快速简便的解决方案来复制任何对象及其所有内容,无论它是如何构建的以及它包含的内容,请在此处查看我的答案:Bug in using Object.clone()

回答by Michaela Maura Elschner

IMHO it's as simple as this:

恕我直言,就像这样简单:

  • #clonemust not be called on non-cloneable objects, therefore it is not made public
  • #clonehas to be called by subclasses ob Objectthat implement Cloneable to get the shallow copy of the right class
  • #clone不得在不可克隆的对象上调用,因此它不会公开
  • #clone必须由Object实现 Cloneable的子类 ob 调用以获取正确类的浅拷贝

What's the right scope for methods that shall be callable by subclasses, but not by other classes?

子类可以调用但其他类不能调用的方法的正确范围是什么?

It's protected.

它是protected

Classes implementing Cloneableof course will make this method public so it can be called from other classes.

实现类Cloneable当然会使这个方法公开,以便可以从其他类调用它。