3

How do I make defensive copies of a Mutable Object which contains a mutable field in an Immutable Object?

class ImmutableObject {

  private final MutableObject immutable_field;

  ImmutableObject(MutableObject y) {
    this.immutable_field = y;
  }
}

class MutableObject {

  public int mutable_field;
}
  • The MutableObject does not have a constructor that lets me set the field.
  • The MutableObject's current state should be captured in the Immutable Object and never changed.
unj2
  • 52,135
  • 87
  • 247
  • 375
  • 1
    Sorry for my ignorance, but what is a "defensive copy" of an object? What are the use cases? – Xavier Ho Jun 02 '10 at 03:28
  • 2
    It's not really immutable if it contains a mutable object is it?... You won't have the security and concurrency goodies that come with immutable objects. – Artefacto Jun 02 '10 at 03:29
  • See even though I think the immutable_field cannot be accessed, if someone changes the MutableObject, my field also changes. That is why I need to create a copy of the object so that it points to a newer object that cannot be accessed. This is called "defensive copying". – unj2 Jun 02 '10 at 03:31
  • Maybe clone the object? (in your constructor and your getter method). Does the object implement an interface? If it doesn't, may you implement one and use a wrapper? – Luciano Jun 02 '10 at 03:31
  • @Xavier Ho: a "defensive copy" is a term used in OO languages, typically in Java (but also, for example, in Objective-C). That term is used (and defined), for example, in Joshua Bloch's *Effective Java*, where there's an entire *"item"* devoted to the technique. It is related to mutability of objects and invariants. Joshua Bloch of course states that the real lesson is that you should use immutable objects as much as possible... (hence making techniques such as defensive copies moot). But I don't agree with kunjaan's definition of "immutable". – NoozNooz42 Jun 02 '10 at 04:44
  • Hi NoozNooz, could you clarify your definition of immutable. thanks. – unj2 Jun 02 '10 at 04:45
  • 2
    @kunjaan: An object that encapsulates a mutable object is not, by any stretch of imagination, "immutable". Your comment to *Artefacto* is completely bogus: it's not because a technique called *"defensive copy"* exists that using it shall automagically make your objects "immutable". Naming your main class *ImmutableObject* is silly: *if it contains a mutable object, **defensive copy or no**, your class is not immutable*. – NoozNooz42 Jun 02 '10 at 04:48
  • 1
    @kunjaan: my definition of immutable is the same as Artefacto and the same as anyone else. You're probably the only person to think that because your fields cannot be changed it's still an immutable object even though it contains a mutable object. Your definition is both wrong and plain rubbish. – NoozNooz42 Jun 02 '10 at 04:50
  • 1
    No need to get hostile. I was trying to encapsulate a mutable object into an immutable object. I stripped down everything to the bare minimum and changed the names of the classes to signal which of them need to be immutable. I am just learning here. Please change your pad. – unj2 Jun 02 '10 at 05:14
  • kunjaan is right. Having a final field assigned to a copy (!) of a mutable object makes the surrounding object immutable. – whiskeysierra Jun 02 '10 at 08:31

2 Answers2

7

What you need to do is in

  MutableObject return_immutable_field() {
    return immutable_field;
  }

Change to:

  MutableObject return_immutable_field() {
    MutableObject tmp = new MutableObject();
    tmp.mutable_field = immutable_field.mutable_field;
    return tmp;
  }

For an explanation see http://www.javapractices.com/topic/TopicAction.do?Id=15

Romain Hippeau
  • 24,113
  • 5
  • 60
  • 79
4

Well, assuming that there is nothing to be done about the declaration of the mutable object class, one could leverage reflection (Class.newIntance() and Class.getFields()) to create a new object and copy field values. You could also implement deep copying in this manner. If the class supports serialization, then another hackish approach would be to serialize the object and then save a deserialized copy. If it is possible to fix the design of the mutable object, though, that would be a better approach.

Edit
For the particular example that you've given, Romain's answer does what you want. If you have a general mutable object that doesn't provide a mechanism for copying it and for which the type may not be known until later, then the reflection approach is how one would implement a copy mechanism.

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200