Wednesday, January 20, 2010

Things that Java got wrong: part 1: clone()

 This is the start of a series on some of the what-might-have-beens in Java: facets of the language that, in my opinion, they "got wrong".

But, first, a disclaimer: I love Java and as far as I'm concerned, it's by far the best general purpose and popular language that has ever walked the earth, so to speak.  So while I'm about to be very picky indeed to my favorite toy, I still love ya baby!

clone()

The ability of a class to have its objects cloned is determined by the existence of a marker interface Cloneable.  If you override the clone() method in your Cloneable class (don't forget to make it public) you buy the privilege of not having it throw a CloneNotSupportedException when you call clone() on that object.  The super.clone() method will actually do most of the heavy lifting for you.  But it only does a field-by-field copy.  It doesn't clone any of the fields itself, it just copies them.  Now, wouldn't it be nice if we could provide an annotation, for example @Clone(deepcopy=true), for those fields on which we want to perform a deep copy.  Similarly for shallow copies, such as implemented by HashMap and ArrayList.

The way we have to do it now is to invoke clone() on those fields (and naturally, we have to implement the clone() method in the (Cloneable) type of the field).  And here's the annoying part.  When a field is marked final, because it's initialized only by the constructor(s), you have to mark it as non-final just so that you can assign the result of cloning it to the field.  Even without the annotations suggested above, the Java designers could have given the clone() method, if it exists, special privileges on a par with constructors.  It sounds a bit hokey, I agree.  But clearly the Object.clone() method effectively has these privileges (when it does a field-by-field copy).  It's only at our level that such privileges are missing.

OK, back to work!

No comments:

Post a Comment