It is a bad idea to make an immutable object Cloneable. This is why String is not Cloneable. Immutable BigInteger and BigDecimal are also not Cloneable.
But mutable StringBuilder and StringBuffer cannot be cloned!
What is the reason behind that desicion?
Yes, I can use "copy constructor" new StringBuilder(CharSequence seq) but what is the design principle/reasoning to supply a copy constructor and prohibit cloning?
Because Cloneable was mistake from beginning.
It have difficult to use interface (you have to cast result back)
Unclean semantic (will it be deep clone or shallow clone?)
It is difficult to customize
All of these made this interface unpopular.
So answer is: no one wants it.
EDIT
If you want to know why it will be bad idea to implement Cloneable in StringBuilder: Cloneable have shallow-copy semantic and this make difficult to maintain invariants (this is generic problem with shallow copy of mutable objects). For example there is optimizations in toString which will be broken in case we clone it.
Related
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.
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.
This question already has answers here:
clone() vs copy constructor vs factory method?
(10 answers)
Closed 8 years ago.
clone method vs copy constructor in java. which one is correct solution. where to use each case?
Clone is broken, so dont use it.
THE CLONE METHOD of the Object class
is a somewhat magical method that does
what no pure Java method could ever
do: It produces an identical copy of
its object. It has been present in the
primordial Object superclass since the
Beta-release days of the Java
compiler*; and it, like all ancient
magic, requires the appropriate
incantation to prevent the spell from
unexpectedly backfiring
Prefer a method that copies the object
Foo copyFoo (Foo foo){
Foo f = new Foo();
//for all properties in FOo
f.set(foo.get());
return f;
}
Read more
http://adtmag.com/articles/2000/01/18/effective-javaeffective-cloning.aspx
Have in mind that clone() doesn't work out of the box. You will have to implement Cloneable and override the clone() method making in public.
There are a few alternatives, which are preferable (since the clone() method has lots of design issues, as stated in other answers), and the copy-constructor would require manual work:
BeanUtils.cloneBean(original) creates a shallow clone, like the one created by Object.clone(). (this class is from commons-beanutils)
SerializationUtils.clone(original) creates a deep clone. (i.e. the whole properties graph is cloned, not only the first level) (from commons-lang), but all classes must implement Serializable
Java Deep Cloning Library offers deep cloning without the need to implement Serializable
clone() was designed with several mistakes (see this question), so it's best to avoid it.
From Effective Java 2nd Edition, Item 11: Override clone judiciously
Given all of the problems associated with Cloneable, it’s safe to say
that other interfaces should not extend it, and that classes
designed for inheritance (Item 17) should not implement it. Because of
its many shortcomings, some expert programmers simply choose never to
override the clone method and never to invoke it except, perhaps, to
copy arrays. If you design a class for inheritance, be aware that if
you choose not to provide a well-behaved protected clone method, it
will be impossible for subclasses to implement Cloneable.
This book also describes the many advantages copy constructors have over Cloneable/clone.
They don't rely on a risk-prone extralinguistic object creation mechanism
They don't demand unenforceable adherence to thinly documented conventions
They don't conflict with the proper use of final fields
They don't throw unnecessary checked exceptions
They don't require casts.
All standard collections have copy constructors. Use them.
List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);
Keep in mind that the copy constructor limits the class type to that of the copy constructor. Consider the example:
// Need to clone person, which is type Person
Person clone = new Person(person);
This doesn't work if person could be a subclass of Person (or if Person is an interface). This is the whole point of clone, is that it can can clone the proper type dynamically at runtime (assuming clone is properly implemented).
Person clone = (Person)person.clone();
or
Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho's answer
Now person can be any type of Person assuming that clone is properly implemented.
See also: How to properly override clone method?. Cloning is broken in Java, it's so hard to get it right, and even when it does it doesn't really offer much, so it's not really worth the hassle.
Great sadness: neither Cloneable/clone nor a constructor are great solutions: I DON'T WANT TO KNOW THE IMPLEMENTING CLASS!!! (e.g. - I have a Map, which I want copied, using the same hidden MumbleMap implementation) I just want to make a copy, if doing so is supported. But, alas, Cloneable doesn't have the clone method on it, so there is nothing to which you can safely type-cast on which to invoke clone().
Whatever the best "copy object" library out there is, Oracle should make it a standard component of the next Java release (unless it already is, hidden somewhere).
Of course, if more of the library (e.g. - Collections) were immutable, this "copy" task would just go away. But then we would start designing Java programs with things like "class invariants" rather than the verdammt "bean" pattern (make a broken object and mutate until good [enough]).
Clone does not call the object constructor to create a copy of the object. So what algorithm does clone use ?
I am looking for implementation details of the native method clone. Any pointers will be appreciated.
Note that I am aware of the shortcomings of clone.
protected native Object clone(). I don't know exactly (I need to take a look at the native code) but it makes a new instance of the object inside the JVM and copies all fields.
But you should avoid using clone() - it is hard to get it right. Look at this question for more details
How it works is laid out in the Javadoc:
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. Note that all arrays are considered to implement the interface Cloneable. Otherwise, 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.
E.g., a naive, shallow field-by-field copy, very nearly (but probably not quite) just a bit-for-bit copy of the object.
I am looking for implementation details of the native method clone.
That will vary from JVM implementation to JVM implementation. It's likely to be quite an efficient operation, though, if that's your concern.
In terms of JNI, clone is (or could be) implemented using the AllocObject method which creates a new object without invoking any constructor (as opposed to NewObject). When you have the new object, reflection is used to shallowly copy all fields.
But then again, the clone/Clonable mechanism is fundamentally broken in Java. Joshua Bloch has a section about it in Effective Java. There is also several related SO questions about it.
The Object.clone() implementation is a native method that checks that the object's class implements Cloneable, and then simply allocates a new instance and does a field-by-field shallow copy. The copying is most likely done using a memory copy - there's no need for it to do anything more fancy. (But if you really want to know, look at the OpenJDK source code.)
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.