No you are not forced to override the clone method. In inheritance, when you inherit a class, you are not forced to override it's method. Its modifier being public or protected doesn't make much of a difference.
Creating a copy using the clone() methodThe class whose object's copy is to be made must have a public clone method in it or in one of its parent class. Every class that implements clone() should call super. clone() to obtain the cloned object reference. The class must also implement java.
Utilize Object clone() method by calling super. clone() in overridden clone method, then make necessary changes for deep copying of mutable fields. If your class is serializable, you can use serialization for cloning.
If you override the clone method() of the object class and declare it protected it is access able only to the subclasses of the current class.
Do you absolutely have to use clone
? Most people agree that Java's clone
is broken.
Josh Bloch on Design - Copy Constructor versus Cloning
If you've read the item about cloning in my book, especially if you read between the lines, you will know that I think
clone
is deeply broken. [...] It's a shame thatCloneable
is broken, but it happens.
You may read more discussion on the topic in his book Effective Java 2nd Edition, Item 11: Override clone
judiciously. He recommends instead to use a copy constructor or copy factory.
He went on to write pages of pages on how, if you feel you must, you should implement clone
. But he closed with this:
Is all this complexities really necessary? Rarely. If you extend a class that implements
Cloneable
, you have little choice but to implement a well-behavedclone
method. Otherwise, you are better off providing alternative means of object copying, or simply not providing the capability.
The emphasis was his, not mine.
Since you made it clear that you have little choice but to implement clone
, here's what you can do in this case: make sure that MyObject extends java.lang.Object implements java.lang.Cloneable
. If that's the case, then you can guarantee that you will NEVER catch a CloneNotSupportedException
. Throwing AssertionError
as some have suggested seems reasonable, but you can also add a comment that explains why the catch block will never be entered in this particular case.
Alternatively, as others have also suggested, you can perhaps implement clone
without calling super.clone
.
Sometimes it's more simple to implement a copy constructor:
public MyObject (MyObject toClone) {
}
It saves you the trouble of handling CloneNotSupportedException
, works with final
fields and you don't have to worry about the type to return.
The way your code works is pretty close to the "canonical" way to write it. I'd throw an AssertionError
within the catch, though. It signals that that line should never be reached.
catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
There are two cases in which the CloneNotSupportedException
will be thrown:
Cloneable
(assuming that the actual cloning eventually defers to Object
's clone method). If the class you are writing this method in implements Cloneable
, this will never happen (since any sub-classes will inherit it appropriately).Cloneable
.The latter case cannot occur in your class (as you're directly calling the superclass' method in the try
block, even if invoked from a subclass calling super.clone()
) and the former should not since your class clearly should implement Cloneable
.
Basically, you should log the error for sure, but in this particular instance it will only happen if you mess up your class' definition. Thus treat it like a checked version of NullPointerException
(or similar) - it will never be thrown if your code is functional.
In other situations you would need to be prepared for this eventuality - there is no guarantee that a given object is cloneable, so when catching the exception you should take appropriate action depending on this condition (continue with the existing object, take an alternative cloning strategy e.g. serialize-deserialize, throw an IllegalParameterException
if your method requires the parameter by cloneable, etc. etc.).
Edit: Though overall I should point out that yes, clone()
really is difficult to implement correctly and difficult for callers to know whether the return value will be what they want, doubly so when you consider deep vs shallow clones. It's often better just to avoid the whole thing entirely and use another mechanism.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With