In the astonishing book "Java the Good Parts" the author gives some code that returns a copy of an object within its getter method (to be used with an well-encapsulated field) and then states:
This approach, which tries to return copies of private data rather than references to that private data, is generally a good idea
Why is that so? I thought a goal of encapsulation was to make sure that nobody can actually alter private members. So why would I write something like this
private someType fieldName = new someType();
...
while defining its getter like this (assuming that there is some sort of copy-constructor)
someType getSomething()
{
return new someType(fieldName);
}
From what I know now, I mean before you guys pop in is:
that this makes sense in so far that it services garbage collection, since this approach doesn't maintain references to the actual object.
it also may be understandable from an inner-class perspective, from which any method could alter any field accesable via the reference.
But I don't suspect the two reasons for doing so to be what's really beyond that issue.
When types are mutable, it's often useful to return a copy so that a client can't fundamentally modify your data, at least without telling you about it. Consider:
public class Person {
private Date dateOfBirth;
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
// Do some validation, e.g. that it's after 1800
this.dateOfBirth = dateOfBirth;
}
}
That looks okay, right? But what about:
Person person = new Person();
person.setDateOfBirth(new Date()); // Now... fine.
// Aha! Modify the Date to a very long time ago. Now anyone else
// using the Person will be messed up...
person.getDateOfBirth().setTime(Long.MIN_VALUE);
If getDateOfBirth
returns a copy instead, then any changes the caller makes to the Date
object that the return value refers to will be irrelevant to anyone else. The Person
object is still valid, because it only has a valid date. Of course, this should be documented so that whoever wrote the above code would expect it not to affect the Person
object, due to a copy being returned.
A better solution than all of this copying is to favour immutable types, however - when you've got a reference to an immutable object, you can share that as widely as you like, knowing that no-one can change its state under your feet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With