How Does Cloneable Work in Java and How to Use It

How does Cloneable work in Java and how do I use it?

The first thing you should know about Cloneable is - don't use it.

It is very hard to implement cloning with Cloneable right, and the effort is not worth it.

Instead of that use some other options, like apache-commons SerializationUtils (deep-clone) or BeanUtils (shallow-clone), or simply use a copy-constructor.

See here for the views of Josh Bloch about cloning with Cloneable, which explains the many drawbacks of the approach. (Joshua Bloch was a Sun employee, and led the development of numerous Java features.)

Why we use cloneable interface in java while making clones of the object?

The clone situation is unique and is rather anti-java-like - there's a reason its not recommended to use it in the first place. The way Cloneable is used in the JDK is not something you should be taking notes on - this isn't how to design APIs, nothing else in the java ecosystem works this way.

Weirdly, this is a common thing: The core parts of java often aren't java-like. For example, nobody in their right mind would make an API that defines an application by 'it has a method with the signature public static void main(String[] args). The obvious design principle would be to make an abstract class or interface with an abstract start() method, and to make a java app you write a class that has a no-args constructor and implements/extends that interface/class. Same story for arrays: They are weird - their toString, equals, and hashCode implementations are surprising, to say the least. They aren't entirely type-safe either.

The reasons for all of this are historic: To explain them, you need to know about all sorts of things that were relevant at the time, but aren't important anymore and haven't been for decades.

Cloneable is no different. Let me explain why it works that way:

The 'system' of cloning is offered by the JDK itself, it's a built-in thing that an ordinary library could not easily make. Kinda how "java SomeClass invokes its main method" is part of java itself.

The system, however, needs an opt-in mechanism: The act of cloning may not make sense (what does it mean to 'clone' an InputStream representing a TCP network connection's incoming bytes? What does it mean to 'clone' the value of an enum which tries to guarantee that only one instance ever exists? What does it mean to 'clone' a singleton?)

Thus, 'just make all objects cloneable' is dangerous, so java didn't want to do that: They want you to opt in to it. Java wants the author of a class to explicitly say: Yup. I am clonable, using the standard mechanism (which deep-copies all fields, if memory serves).

That is what Cloneable is for! - that's how you say: Yup. I'm good with it. By implementing that. It's a flag.

Java could also have decided to do something like:

/** @cloneable */
public class Something {}

instead, but they didn't. If it had been designed in this more modern age, perhaps it would have looked like:

@Cloneable
public class Something {}

But annotations were introduced in java 1.5 as a demo feature in 1.6 properly. The cloneable interface is as old as java 1.0 - over a decade earlier. "add an interface that defines nothing" was the standard way to flag class properties back then, even if it isn't now.

NB: You don't just implements Cloneable, you also make a public clone method. The implements Cloneable part tells the cloning system: You may clone this class, for example even if it is part of the deep structure of an encompassing object that is being cloned. Making a clone method that invokes the protected JVM-provided clone() method that j.l.Object has is how you expose the API. Maybe you want to name it copy instead, or maybe you want cloning but not as part of your public API. Your question isn't about how to use clone, but why it works like it is - my advice if you want to use it is simple. Don't, write clone code yourself, or better yet, design your API with more immutables so that cloning is no longer neccessary.

What is the point of the cloneable interface?

To answer your first question, you must implement the Clonable interface for the clone() method to work since Object's clone checks that the interface is implemented otherwise it will throw an exception.

Using clone() is a bad idea. It was one of the original ideas in Java that didn't work out. There are some design issues including it usually being a shallow copy. If you want to make a copy or a deep copy of an object, it's best to create a copy constructor or a copy method to do it without using clone. Using clone() correctly is hard.

If really you want to use the clone(), then read this blog post which explains how to use clone(). Basically there are 5 points to remember when using clone():

1) Clone method is used to create a copy of object in Java. In order to use clone() method, class must implement java.lang.Cloneable interface and override protected clone() method from java.lang.Object. A call to clone() method will result in CloneNotSupportedException, if that class doesn't implement Cloneable interface.

2) No constructor is called during cloning of Object in Java.

3) Default implementation of clone() method in Java provides "shallow copy" of object, because it creates copy of Object by creating new instance and then copying content by assignment, which means if your Class contains a mutable field, then both original object and clone will refer to same internal object. This can be dangerous, because any change made on that mutable field will reflect in both original and copy object. In order to avoid this, override clone() method to provide deep copy of object.

4) By convention, clone of an instance should be obtained by calling super.clone() method, this will help to preserve invariant of object created by clone() method i.e. clone != original and clone.getClass() == original.getClass(). Though these are not absolute requirement as mentioned in Javadoc.

5) Shallow copy of an instance is fine, until it only contains primitives and Immutable objects, otherwise, you need to modify one or more mutable fields of object returned by super.clone, before returning it to caller.

Why do we implement Cloneable even if we can go for deep cloning using the following snippet

Is it necessary to implement Cloneable to clone? Yes.The clone() method is having protected access modifier with the following Javadoc explantion :-

This method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a shallow copy of this object, not a deep copy operation.

Your method testClone although may be correct in cloning behavior but is not a Cloneable Object in itself.A Cloneable object must implement Cloneable interface and preferably have a public access for clone() so that it can be used outside the class.

Someone reaading your class will have a hard time understanding the importance of testClone() method.



Related Topics



Leave a reply



Submit