Java's clone syntax seems to suck

From Nick Jenkins
Jump to: navigation, search

The design of "clone()" in Java really seems to suck. What if I want to make a deep copy of an object? Object.clone() usually (and I do stress usually) makes a shallow copy.

Now, on one hand, Java's "everything is an object, and you manipulate objects with references, and therefore any changes to the object affect all references to that object" design is a pretty good one. It makes it much easier than languages like PHP to solve some problems with objects. In PHP4, everything is a copy by default, and although you can get references, those references use a different syntax, which you have use over and over. PHP's reference syntax becomes a real pain if you're working with objects - forget it just once, and you'll silently get a deep copy, not a reference, which can occasionally lead to subtle and non-trivial bugs.

However, an annoyance with Java is the almost opposite problem. Operating with a reference in Java is a breeze - you don't have to do anything special or use any special syntax. Want a copy though? Especially, do you want a deep copy? Oh my, what a pain in the ass! Getting an object to copy its data members is quite easy. The problem is that every aggregated object has to be copied too - and not just a copy, a deep copy. If those are aggregated objects are Collection objects from the JDK, they probably won't know how to deep copy themselves, only how to shallow copy themselves. So you have to go through all of their contents, and deep copy those. Of course, if you have a Collection object containing Collection objects which contains other objects, then you've got to make this all work yourself. What fun!

A sensible solution might have been to have the root Object class have two methods - deepClone() and shallowClone() - both with a well-defined meaning (which if you read the JDK, you'll see the current root Clone() method lacks). That way, getting the right kind of copy would be much easier.

Update: after writing this, I found that Eiffel's universal base class supports "deep_copy" and "deep_clone" methods, so the designers of that language evidently saw the need for just such a solution.