107

I would like to know the following:

  1. Cloneable means we can have a clone or a copy of objects, by implementing the Cloneable interface. What are the advantages and disadvantages of doing that?
  2. How does the recursive cloning happen if the object is a composite object?
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
daydreamer
  • 87,243
  • 191
  • 450
  • 722

6 Answers6

169

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.)

isapir
  • 21,295
  • 13
  • 115
  • 116
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 1
    I linked Bloch's words (instead of quoting them) – Bozho Nov 02 '10 at 20:44
  • 3
    Note that Block says not to use Cloneable. He does not say don't use cloning (or at least I hope not). There are many ways to implement cloning simply that are far more efficient than classes like SerializationUtils or BeanUtils that use reflection. See my post below for an example. – Charles Feb 15 '14 at 22:15
  • what's the alternative to a copy constructor when defining interfaces? simply add a copy method? – benez Feb 19 '19 at 01:50
  • @benez I would say yes. since java-8 you can have `static` methods in interfaces, so just provide a `static WhatEverTheInterface copy(WhatEverTheInterface initial)`? but I wonder what this gives you, since you copy fields from an object while cloning, but an interface defines only methods. care to explain? – Eugene Jul 29 '19 at 19:53
  • I am sorry I am going to down vote this, it is a misguided advise. SerializationUtils are expensive and it is well documented in their own java docs, further more the question was how to use cloneable and a proper example should have been given instead of incorrect advise. I agree a disclaimer can be added but don't use cloneable is flat out wrong answer. – MG Developer Nov 07 '21 at 19:09
  • I would like to hear from Java officially to deprecate the feature rather than one architect claiming it is broken. I personally do not see it's broken if you do it properly. – MG Developer Nov 07 '21 at 19:18
43

Cloneable itself is unfortunately just a marker-interface, that is: it does not define the clone() method.

What is does, is change the behavior of the protected Object.clone() method, which will throw a CloneNotSupportedException for classes that do not implement Cloneable, and perform a member-wise shallow copy for classes that do.

Even if this is the behavior you are looking for, you'll still need to implement your own clone() method in order to make it public.

When implementing your own clone(), the idea is to start with the object create by super.clone(), which is guaranteed to be of the correct class, and then do any additional population of fields in case a shallow copy is not what you want. Calling a constructor from clone() would be problematic as this would break inheritance in case a subclass wants to add its own additional cloneable logic; if it were to call super.clone() it would get an object of the wrong class in this case.

This approach bypasses any logic that may be defined in your constructors though, which could potentially be problematic.

Another problem is that any subclasses that forget to override clone() will automatically inherit the default shallow copy, which is likely not what you want in case of mutable state (which will now be shared between the source and the copy).

Most developers don't use Cloneable for these reasons, and simply implement a copy constructor instead.

For more information and potential pitfalls of Cloneable, I highly recommend the book Effective Java by Joshua Bloch

Luke Hutteman
  • 1,921
  • 13
  • 11
13
  1. Cloning invokes an extra-linguistic way of constructing objects - without constructors.
  2. Cloning requires you to treat somehow with CloneNotSupportedException - or to bother client code for treating it.
  3. Benefits are small - you just don't have to manually write a copying constructor.

So, use Cloneable judiciously. It doesn't give you sufficient benefits in comparison with the effort you need to apply to do everything right.

karobar
  • 1,250
  • 8
  • 30
  • 61
Vladimir Ivanov
  • 42,730
  • 18
  • 77
  • 103
  • As Bozho said, don't use Cloneable. Instead, use a copy-constructor. http://www.javapractices.com/topic/TopicAction.do?Id=12 – Bane Nov 02 '10 at 20:47
  • @Bane, what if you don't know the type of the object to clone, how would you know which class's copy constructor to invoke? – Steve Kuo Nov 02 '10 at 22:55
  • @Steve: I don't follow. If you are going to clone an object, I presume you already know what type it is -- after all, you have the object in-hand that you are planning on cloning. And if there is a situation where your object has lost it's specific-type to a more generic one, couldn't you evaluate it using a simple 'instance of'??? – Bane Nov 03 '10 at 13:47
  • 4
    @Bane: Suppose you have a list of objects all derived from type A, maybe with 10 different types. You don't know what the type of each object is. Using instanceof in this case is a VERY bad idea. If you add another type, every time you do this you would have to add another instanceof test. And, what if the derived classes are in another package you can't even access? Cloning is a common pattern. Yes, the java implementation is bad, but there are many ways around it that will work just fine. A copy constructor is not an equivalent operation. – Charles Feb 15 '14 at 21:53
  • @Charles: In the absence of a detailed-example, and lacking recent experience with dealing with this sort of problem, I'll have to defer to Bloch. Item #11. It's long and a bit of hard read, but it basically says "avoid cloneable whenever you can, copy constructors are your friend". – Bane Feb 27 '14 at 22:39
8

Cloning is a basic programming paradigm. The fact that Java may have implemented it poorly in many ways does not at all diminish the need for cloning. And, it is easy to implement cloning that will work however you want it to work, shallow, deep, mixed, whatever. You can even use the name clone for the function and not implement Cloneable if you like.

Suppose I have classes A, B, and C, where B and C are derived from A. If I have a list of objects of type A like this:

ArrayList<A> list1;

Now, that list can contains objects of type A, B, or C. You don't know what type the objects are. So, you can't copy the list like this:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(new A(a));
}

If the object is actually of type B or C, you will not get the right copy. And, what if A is abstract? Now, some people have suggested this:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    if(a instanceof A) {
        list2.add(new A(a));
    } else if(a instanceof B) {
        list2.add(new B(a));
    } else if(a instanceof C) {
        list2.add(new C(a));
    }
}

This is a very, very bad idea. What if you add a new derived type? What if B or C are in another package and you don't have access to them in this class?

What you would like to do is this:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(a.clone());
}

Lots of people have indicated why the basic Java implementation of clone is problematic. But, it's easily overcome this way:

In class A:

public A clone() {
    return new A(this);
}

In class B:

@Override
public B clone() {
    return new B(this);
}

In class C:

@Override
public C clone() {
    return new C(this):
}

I'm not implementing Cloneable, just using the same function name. If you don't like that, name it something else.

Charles
  • 1,084
  • 11
  • 14
  • 1
    I just saw this after replying to your comment in separate answer; I see where you are going now, however 2 things: 1) the OP asked specifically about using Cloneable (not about the generic concept of cloning), and 2) you are splitting hairs here a bit in trying to distinguish between a copy-constructor and the generic concept of cloning. The idea you convey here is valid, but at it's root you are just using a copy-constructor. ;) – Bane Feb 27 '14 at 22:53
  • Although I do want to say that I agree with your approach here, that of including an A#copyMethod(), rather than forcing the user to call the copy-constructor directly. – Bane Feb 27 '14 at 22:55
  • I am upvoting this as it accurately provides the example for the question asked. The most voted answer is not always correct advise. SerializationUtils are very bad for performance and similar BeanUtils. The copy constructor is the win win, however clone itself is not bad if implemented properly. – MG Developer Nov 07 '21 at 19:21
5

A) There are not a whole lot of advantages of clone over a copy constructor. Probably the biggest one is the ability to create a new object of the exact same dynamic type (assuming the declared type is clonable and has a public clone method).

B) The default clone creates a shallow copy, and it will remain a shallow copy unless your clone implementation changes that. This can be difficult, especially if your class has final fields

Bozho is right, clone can be difficult to get right. A copy constructor/factory will serve most needs.

ILMTitan
  • 10,751
  • 3
  • 30
  • 46
0

What are disadvantages of Cloneable?

Cloning is very dangerous if the object whom you are copying has composition.You need to think about below possible side effect in this case because clone creates shallow copy:

Let say you have one object to handle db related manipulation. Say, that object has Connection object as one of the property.

So when someone creates clone of originalObject, The object being created, let say, cloneObject. Here the originalObject and cloneObject hold the same reference for Connection object.

Let say originalObject closes the Connection object, so now the cloneObject will not work because the connection object was shared between them and it was actaually closed by the originalObject.

Similar problem may occur if let say you want to clone a object which has IOStream as a property.

How does the recursive cloning happen if the object is a composite object?

Cloneable performs shallow copy. Meaning is that data of original object and clone object will point to the same reference/memory. contrary in the case of deep copy, data from memory of original object is copied to the memory of clone object.

027
  • 1,553
  • 13
  • 23
  • Your last paragraph is very confused. `Cloneable` doesn't perform a copy, `Object.clone` does. "Data from memory of original object is copied to memory of clone object" is precisely what `Object.clone` does. You need to talk about memory of referenced objects to describe deep copying. – aioobe Mar 27 '18 at 05:44