Why no default clone() in Cloneable in Java 8

荒凉一梦 提交于 2019-11-30 08:55:59

Your question is somewhat broad and more of a discussion, but I can shed some light on this matter.

In Effective Java™, Joshua Bloch gives quite the rundown on the situation. He opens with a bit of history behind Cloneable

The Cloneable interface was intended as a mixin interface for objects to advertise that they permit cloning. Unfortunately, it fails to serve this purpose. Its primary flaw is that it lacks a clone method, and Object’s clone method is protected. You cannot, without resorting to reflection, invoke the clone method on an object merely because it implements Cloneable.

and continues with the reasoning

[Cloneable] determines the behavior of Object’s protected clone implementation: if a class implements Cloneable, Object’s clone method returns a field-by-field copy of the object... This is a highly atypical use of interfaces and not one to be emulated. Normally, implementing an interface says something about what a class can do for its clients. In the case of Cloneable, it modifies the behavior of a protected method on a superclass.

and

If implementing the Cloneable interface is to have any effect on a class, the class and all of its superclasses must obey a fairly complex, unenforceable, and thinly documented protocol. The resulting mechanism is extralinguistic: it creates an object without calling a constructor.

There are a lot of details that go into this, but to note just one problem:

The clone architecture is incompatible with normal use of final fields referring to mutable objects.

I think this is enough to reason against having a default method in the interface do the cloning. It would be extremely complicated to implement it correctly.

My experience is probably far from being mainstream, but I use clone() and support the current design of Cloneable. Probably it would be better to have it as annotation instead, but Cloneable appeared long before the annotations. My opinion is that Cloneable is a low-level thing and nobody should do something like obj instanceof Cloneable. If you are using Cloneable in some business-logic, it's much better to declare your own interface or abstract class which exposes clone() to public and implement it in all of your business-logic objects. Sometimes you will probably want not to expose clone() actually, but create your own method which uses clone() internally.

For example, consider that you have an hierarchy of named objects where name cannot be changed after construction, but you want to allow cloning them with new name. You can create some abstract class like this:

public abstract class NamedObject implements Cloneable {
    private String name;

    protected NamedObject(String name) {
        this.name = name;
    }

    public final String getName() {
        return name;
    }

    public NamedObject clone(String newName) {
        try {
            NamedObject clone = (NamedObject)super.clone();
            clone.name = newName;
            return clone;
        }
        catch(CloneNotSupportedException ex) {
            throw new AssertionError();
        }
    }
}

Here even though you implement Cloneable, you want to use clone(), but don't want to expose it publicly. Instead you provide another method which allows to clone with another name. So having public clone() in Cloneable would unnecessarily pollute the public interface of your classes.

Another case where I use Cloneable is the implementation of Spliterator.trySplit(). See the implementation of simple spliterator which returns given number of constant objects. It has four specializations (for Objects, ints, longs and doubles), but thanks to clone() I can implement trySplit() only once in the superclass. Again, I don't want to expose clone(), I just want to use it by myself.

So to conclude, not having clone() method in Cloneable interface is actually more flexible as it allows me to decide whether I want to have it public or not.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!