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.