Behaviour towards object cloning in Java - java

I am studying Java because I need it as a prerequirement in one of my college courses.
I come from a C++ background, so understanding the logic underlying OOP is not particularly difficult.
But there are several differences between the two languages, and one I just cannot figure out is the object cloning feature present in Java.
The problem recalls me that of the copy constructor for C++, but the implications are just different.
In Java, there are no destructors and memory is managed by a garbage collector, so there are not the heap memory issues you face in C++. The problem is limited to sharing variables.
Now, reading around, I found that object cloning (unlike copy constructors) is not a feature that an OOP language should provide, as it creates another instance of an object skipping the construction phase. Moreover, clone() cannot manipulate final fields properly, and skip initialization blocks. The same logic behind clonation is "wrong" because "Cloneable" is just like an empty interface, provided only to make a type check in Object.clone(), to raise an exception if the type of the object is not Cloneable.
All the cloning mechanism seems to rely on the Object.clone() method, which allocates memory properly. Each subtype in the class hierarchy supporting clone(), should make a call to "super.clone()" until the Object one is called to allocate all necessary fields.
But what happens if a subtype, implementing the Cloneable interface, extends a supertype not doing so?
I'm studying from "Arnold, Gosling, Holmes", and one of the defined behaviours towards clone is: "Allow subclasses to support clone but don't publicly support it. Such a class doesn't implement Cloneable, but if the default implementation of clone isn't correct, the class provides a protected clone implementation that clones its fields correctly".
This way, calling super.clone(), in the end we will bump into the protected clone() method of the superclass, but such method cannot rely on Object.clone(), because the superclass itself doesn't implement Cloneable. Using the new operator would be an error, because an instance of the superclass would be created, with some missing fields.
So, is supporting clone() (with a protected method) in a non-Cloneable class really useful?
And how can one solve the problem of a Cloneable subtype with non-Cloneable supertype?

But what happens if a subtype, implementing the Cloneable interface, extends a supertype not doing so?
If it just implements Cloneable without actually overriding clone() (yes, that's also possible!), then no harm is done.
If it overrides clone() and returns an instance which was not retrieved from super.clone(), then it has broken all its subclasses. This is one of the acknowledged pitfalls of clone() (covered in Effective Java).
how can one solve the problem of a Cloneable subtype with non-Cloneable supertype?
As explained above, this is not an issue as long as the non-cloneable supertype does not override clone() (and yes, that's yet another possibility!) or does override it, but in a compliant manner.

how can one solve the problem of a Cloneable subtype with non-Cloneable super type?
Actually this is not a problem. Think of class Object: this is a non-Cloneable type, and used as super type of any Cloneable type. You can create a Cloneable subtype of any type T. The only thing that matters: is the 'clone' operation implemented correctly for that type T (and its super types). For the class Object this is will return a field-wise, shallow copy of the original object, with the same class as the original object.
I.e. not every type in the super class thread of a sub class must implement Cloneable.
... is supporting clone() (with a protected method) in a non-Cloneable class really useful?
Yes. E.g. see the default implementation of clone() in the (non-Cloneable) class Object.

Related

Java Cloneable without an implementation

I am in the process of migrating to java from c++ and consider myself a java noob. I have been looking recently at a vast code base with several examples of the kind public class Myclass implements Cloneable{...} with no implementation of the clone function. I fail to understand the advantages of this pattern. Are there any? If you choose not to implement the clone function, why derive it from Cloneable? Also are there any lombok anotations which provide some default clone functions?
If a class does not implement the Cloneable interface, calling clone on an instance of the class results in a CloneNotSupportedException. The java.lang.Object already implements a clone method (this method is not abstract), so subclasses are not required to implement it. The clone method of java.lang.Object performs a shallow copy of the instance.
If you choose not to implement the clone function, why derive it from
Cloneable?
The clone() method doesn't derive from the Cloneable interface. It comes from the Object class.
Cloneable is simply a marker interface. It is used at runtime to valid the behavior if the clone() method is called on a instance of a class.
Java has chosen a design model where by default the object owns the clone() method. It is a design choice you may like or not but anyway, it is like that
Concretely, if you call clone() on a object and the class of the object doesn't implement Clonable, the JVM will at runtime throw a CloneNotSupportedException exception. In a same way, some classes throw UnsupportedOperationException if one of their method is not implemented.
Also are there any lombok anotations which provide some default clone
functions?
By default, clone() performs a shallow copy of the current object. That is, a new instance is created for the object you are cloning but all object fields that it owns are not cloned. Indeed, the fields of the cloned object still reference the same objects than those in the original instance. Only fields with primitive types (int, float, boolean, etc...) are cloned.
If you need to have a different behavior in the clone() method, Lombok cannot guess what is the behavior you want to have. So, no it makes no sense to use it to generate the implementation of the clone() method.
There is actually a #Wither annotation in lombok:
https://projectlombok.org/features/experimental/Wither.html
But you could also just create a new object passing parameters to a constructor.

Purpose of cloning in Java

I was going through the "special" features of Java, and started reading up on Cloning.
So currently what I understand is Cloning can be used to get a identical copy of an object. To do this you implement the Cloneable interface and override the clone method of Object(Which is really weird IMO)
My questions is more towards the comparison between C++ and Java. Why exactly is a separate clone method required when we already have support for copy constructors. Was there a historical reason on why cloning was thought of as must have feature?
PS: I am not asking about the need to "clone" as in what is the need of cloning a object in Java, what I am asking is the need for Cloneable and the clone method, when Java already supports copy constructors.
IMO you question has two parts.
What is the need for the Cloneable interface?
The Cloneable interface is also known as a marker interface, which means that it does not have any methods, its whole purpose is to tell you, the user of that class, that it implements the clone() method which is inherited from Object. This enables you to do a check before calling the clone() method:
Animal a = new Dog();
Animal b;
if (a instanceof Cloneable)
b = a.clone();
This happens pretty often in Java; see for example the Serializable interface.
Why does Java need a clone() method at all, as it already has copy constructors?
The very short answer is polymorphism. How would you correctly clone a Dog instance, through a reference to an Animal, its super class, if you didn't have the clone() method?
Clone is meant to provide a a separate instance of an object without destroying the cloned one. It's quite useful(it's a must) in prototype pattern.
Copy constructor is usually called in C++ when passing by value (you can do use it at construction time as well, but usually it's called when passing objects through the stack either as paremeters or returns). So often times the initial object gets out of scope.
You can eventually interchange these two if you really want to go at it, but in reality they serve different purposes, and having clarity when one should be used instead of another is very helpful.
Besides the disambiguation of the name, you need to think about polymorphism , where you want to clone the object from a base pointer.
Copy constructors will be called on the type of pointer, while clone (if virtual, like it should be) will be called on the most derived implementation.

What is the point in letting my class implement Cloneable?

I came across some class code that implements Clonable, the documentation states:
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.
Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See Object.clone() for details on overriding this method.
Note that this interface does not contain the clone 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.
I can't understand the point in implementing this class, as said in the docs the .clone method is not implemented in the interface, and I have to implement it. So why use this class? Why won't I just write a method copyClass in my class to make the object copy without the implementation of this class?
To implement the clone method, you simply do:
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
You can of course customize the method to make a deeper copy if needed.
Calling super.clone() is almost mandatory because, unless the class is final and thus can't be overridden, the clone() method must return an instance of the same class as the object on which it's called. So simply creating a new instance and copy the state will work for this class, but not for all the subclasses. Moreover, you don't always have access to all the state contained in superclasses.
In short, you make the protected clone method of Object public. And the first thing that the Object.clone() method does is (this is not the real code, but this is what the method does):
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException();
}
So, Cloneable is just a marker interface to let the Object.clone() method know that it must not throw an exception when called.
This is one of the most badly-designed parts of Java. Usually, you should prefer using a copy contructor instead of using clone().
It allows you to write more generic code. If you have multiple classes implementing Cloneable interface, and want to pass their instances as an argument to method, you don't have to create multiple methods differing with one variable type, you can just use Cloneable t. It's the same with other interfaces. And, the same with every other interface, it's kinda multiple inheritance. Implementing those interfaces makes your code more legible too.
In addition to what others said, Cloneable is often used when implementing prototype design pattern.

use case for clone()

I have never seen clone() method put to use in any real code. I was reading about it and felt that its use could make the code very cumbersome.
is there any specific use case for the clone() method? Under what circumstances would one have to use clone() and why would the use of normal conctructor not suffice?
clone is very convenient to make defensive copies of arrays passed to methods or constructors (as all array types are Cloneable, and the signature for clone()is covariant so that boolean[].clone() actually returns a boolean[] rather than an Object). That's the only really good use I've seen of it in ten years, though...
Josh Bloch in Effective Java also doesn't recommend to use clone () method.
There are several problems with this method:
If cloneable object has not only primitive type fields but also object fields, then cloned object will receive just references to those objects but not real cloned objects. To avoid this all inner objects should be cloneable too.
If you make a subclass of cloneable class, then it's cloneable too (even if you don't want). That's why you should override clone() method in a proper way to avoid possible problems.
When you should use it: never if possible. You should use it very carefully. If all fields in object you want to make cloneable are of primitive type then it's not dangerous. In all other cases think twice before using it.

Confusion about cloneable interface and object.clone() in java

If I have:
class foo implements Cloneable
and then do:
bar = new foo();
bar.clone();
I get a shallow copy without needing to write any bar.clone() code like I normally would need to do when I implement an interface.
My understanding is that an interface's functions must be filled in by the class implementing it, and Object.clone() has no implementation (as per the docs, "The class Object does not itself implement the interface Cloneable")
So where does my shallow clone come from? Where is the code that implements bar.clone() if Object.clone() has no implementation? I'm confused.
Be very careful using clone. In fact, I would avoid it completely. I have never needed it. BUT... that being said, the best discussion of the topic I have ever read is by Joshua Bloch, in Effective Java. Read Item 11: "Override clone judiciously".
PLEASE do yourself a favor and read that item. I actually recommend reading that entire chapter (and the rest of the book). Everything you need to know about clone and why I caution you about it is in there.
Hope this helps.
Object.clone() has an implementation:
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#clone()
This link explains the Cloneable interface:
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Cloneable.html
An object must implement the Cloneable interface in order to call the clone() method, otherwise, it throws a CloneNotSupportedException.
By definition, all classes in Java extend the base Object class, and Object class has a default clone() method, even though Object itself does not implement Cloneable. The Object class's clone() method will be called if you do not override it yourself.
If I have: "class foo implements
cloneable"
and then do: bar = new foo();
bar.clone();
I get a shallow copy without needing
to write any bar.clone() code like I
normally would need to do when I
implement an interface.
That would only work if you are calling it within the class "foo", because the .clone() method inherited from Object is protected.
My understanding is that an
interface's functions must be filled
in by the class implementing it, and
Object.clone() has no implementation
(as per the docs, "The class Object
does not itself implement the
interface Cloneable")
(1) Object.clone() does have an implementation. It makes a shallow copy of the object if the object implements Cloneable. (2) The .clone() method is not part of any interface. (3) Having a .clone() method and implementing the Cloneable interface are completely separate things. You only need to implement the Cloneable interface if you intend to make use of Object's clone method; however, this is the recommended way to write a clone method for your class -- to get its copy from the superclass's clone method, which eventually goes up to Object's clone method.
My understanding is that an interface's functions must be filled in by the class implementing it, and Object.clone() has no implementation (as per the docs, "The class Object does not itself implement the interface Cloneable")
there is a difference between saying Object.clone() has no implementation
and The class Object does not itself implement the interface Cloneable
Object's clone method does have implementation, it does memory-copy of the object who called clone method.
you are right, Object class does not implement cloneable, all it does is check the object is cloneable or not .
the above answer point's you to read some book, i think i can give a quick solution
so to answer your question
So where does my shallow clone come from?
Object's clone method
Where is the code that implements bar.clone() if Object.clone() has no implementation?
it has implementation, written in native code.

Categories