Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return copies of private data rather than references

Tags:

java

reference

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.

like image 428
Andrew Tobey Avatar asked Sep 06 '14 20:09

Andrew Tobey


1 Answers

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.

like image 167
Jon Skeet Avatar answered Nov 10 '22 00:11

Jon Skeet