简体   繁体   中英

Why is Java's Cloneable Interface Not Generic?

Java 5 introduced generics, and they were added to many interfaces in the java.lang package. However, Cloneable did not get generics. I wonder why?


Edit: In reply to the answers of @Jon and @litb, and the comment of @Earwicker, I was thinking Cloneable might be:

public interface Cloneable<T> {
    public T clone();
}

Here T clone(); overrides Object.clone() , giving it a covariant type. I believe this would still be backwards compatible and increase type safety. So why not?


Edit 2: As can be seen in the answers (and comments) below, the interface suggested above would break backwards-compatibility. Since Object.clone() is protected , rewriting it in the interface would force all implementers to provide a public implementation, which class designers might not want to (ie they might opt to keep it protected ).

The Cloneable interface doesn't contain any members. What would be the point of making it generic?

(If Cloneable contained the clone() method, it would make sense - but that's declared in java.lang.Object.)

EDIT: clone() is in java.lang.Object as it has an implementation (which does a field-by-field copy). A better design would be to have something like .NET's MemberwiseClone() as a protected method in Object, and then a public clone() method within the interface itself. I don't know why that design wasn't chosen.

(In .NET, ICloneable isn't generic because it existed before generics - the different nature of .NET generics prevents a previously non-generic type from becoming generic.)

In both Java and .NET, however, the "normal" cloning API is generally regarded as a bad thing, as it says nothing about what depth of cloning should be performed.

If Cloneable was Cloneable<T> , then it would be impossible to do this:

class A extends B implements Cloneable<A>

class B implements Cloneable<B>

You can't implement the same interface with different parameters, and class A implements Cloneable<A> and Cloneable<B> .

java.lang.Cloneable is a marker interface. It's solely for the purpose so that Object.clone can throw an exception to signal a class does not support cloning by using for example

if(!(this instanceof Cloneable))
    throw...;

From the documentation:

The method clone for class Object performs a specific cloning operation. First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown.

It's got no methods. Making it a generic isn't going to be of any use.

This doesn't address your theoretical question, but handles the practical case:

Java 5 has covariant return values and allows broadening the access of methods. So you're free to change the signature for clone() appropriately in subclasses.

public class MyClass implements Cloneable {
    public MyClass clone(){ /* do the right stuff */ }
}

MyClass.clone() is a correct override of Object.clone() , and you won't have to write casts.

As a semi-related thought question: would creating an interface (call it ReallyCloneable) that exposes clone() as a public member be useful?

My contention is that no, it wouldn't. Clonability is intimately linked to concrete class implementation. I can't think of a single use case where I'm likely to say "I have an arbitrary object, and I want a copy of it." The immediate question would be: why do you want that copy?

And the typical answer is so that you can modify the copy without affecting the original. However, to do that you need to know what type of object you're holding, otherwise how would you know what to call to modify it? And if you know that, you'll know whether or not it provides a public clone() method.

But what if you're programming to an interface, such as List? Intelligent (recursive) cloning (versus byte-level object data copy) would be incredibly useful with the Collections framework. But there may be collections (such as those backed by a database) that can't support such an operation, so you can't require List to expose a public clone(). Which drives you to instantiating your own concrete List implementation to copy the contents of the source List.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM