A Funny Java Flavoured Look at the World

Monday, July 10, 2006

What is Defensive Copying

I was wondering what to blog about and then I saw the term defensive copying. I have heard this term mentioned a few times but wasn't sure quite what it was. So I thought it was time for a bit of investigation.

So what is defensive copying, also sometime known as object copy.

Defensive copying is concerned with protecting mutable objects e.g. objects who's state can be modified by the user. If you were pass back the reference of an object any changes a user made to that copy of the object would effect your object because you are only passes a reference to the object and not the actual object itself. This is known as a shallow copy.

To avoid users being able to change the values of your object you can pass back a defensive copy. This means that instead of passing back a reference to your object it passes back a new object but with the same values. This means that any changes the user makes to that copy of the object doesn't change the value/state of your object.

It's an interesting idea but I can't think of a use for this at the moment but I'm sure one day this will come in useful.

Here are a couple of links to some probably better explanations with an example

http://www.javapractices.com/Topic15.cjp


http://en.wikipedia.org/wiki/Defensive_copy

The first site Java practices has lots of useful articles and well worth checking out

4 Comments:

  • In theory, defensive copying is something that should never have to be done. It introduces the possibility of bugs because changes to one copy don't get reflected in the other copy. Well, that was the whole point of making a defensive copy, except now you have two pieces of code that disagree on the value. That may be better or worse than alternative.

    As a very strong rule of thumb, one shouldn't copy mutable objects except for prototyping purposes. And one shouldn't need to copy immutable objects for local use (in the same JVM), although copying them is harmless.

    Alas, the Date class should have been immutable but isn't. The class is Serializable, for heaven's sake… it should have been both immutable and final.

    In my opinion, the preferred approach would be to return a Proxy object that rejects any attempts at modifying the Date object. Unfortunately, that requires changing the contract of the Date class, possibly breaking the code that you hand the proxy object to. Fortunately, UnsupportedOperationException is an unchecked exception so you could force the issue if you really wanted to :-)

    By Blogger Doug, at Tue Jul 11, 07:11:00 am 2006  

  • This sounds like something we'd do to handle persistence timing. A copy can be passed to a user and it's data can be changed until the user decides to persist the changes -- or, if the user decides to cancel their changes, the copy can be destroyed and the original state remains preserved in a protected object.

    An additional benefit (if you build your persistance model to take advantage of it) is you only persist the changes between the original object and the copy -- not the whole object.

    We didn't do this often but when the situation called for it, it's a good pattern.

    By Anonymous Anonymous, at Wed Jul 12, 05:52:00 pm 2006  

  • A simple example where you would do this is the 'Dimension getSize()' api. The size of your component is returned in a Dimension object. If you returned the actual Dimension object you used internally to store your size than the caller could decide to reuse the object returned rather than allocate a new one and inadvertently change the size of the component. Unless, of course, you only returned a copy.

    By Anonymous Anonymous, at Wed Jul 12, 08:11:00 pm 2006  

  • I would like to elaborate on the second comment by giving an example.

    An example is if you are using a cache and you directly modify the objects in the cache. The "clone" or "defensive copy" is needed to handle the case if there is a problem before or even during persisting the object. If you don't use a copy then the modified object still has the changes and the changes were not persisted in the database.


    To get around that modify a "clone" of the object in the cache, not the actual object in the cache.

    By Anonymous Anonymous, at Thu Jul 13, 10:05:00 pm 2006  

Post a Comment

<< Home