Wednesday, January 26, 2005

Read-only properties in Java

C++ has the advantage over Java of supporting operator overloading. In particular, this makes straight-forward to implement read-only and write-only fields (data members in C++ parlance) that actually call back to methods (member functions) when accessed. C# has this feature as well. You cannot do that in Java, but you can at least provide a form of read-only fields.

Traditional Java uses bean-style getters and setters for field access, but there is a more elegant solution for data transfer-style objects:

public class ReadMe {
    public final String title;
    public final String body;

    public ReadMe(final String title, final String body) {
        this.title = title;
        this.body = body;
    }
}

That's it! This is yet another interesting use of the final keyword. The class fields are public, but because they are marked final, they cannot be modified once set and final fields must be initialized during construction. This prevents tampering, and makes the fields read-only. Using ReadMe is trivial:

public void displayReadMe(final ReadMe readMe) {
    createDialog(readMe.title, readMe.body).show();
}

Trivial — no getters or setters required. This idiom is flawed if you need to update the object, however, but field setters have plenty of drawbacks so this complaint is a mild one.

10 comments:

Anonymous said...

Well duh ! Were not amateurs you know dumbass ! How long have you been around ?

Brian Oxley said...

Well, yes, it is trivial. :-) But I spend time every day fixing such trivial problems in mediocre production code. Most unfortunate.

Anonymous said...

Well, read-only access doesn't necessary mean the value is final/constant. Think of an internal state, for example, that can be read, but not be changed from the outside - but internally.

Gerd Riesselmann

Anonymous said...

Getters and setters are never elegant, no matter how you implement them. It leads to code that has more periods than a girls' locker room. Blech.

Tell don't ask.

http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html
http://www.pragmaticprogrammer.com/ppllc/papers/1998_05.html

Aslak

Anonymous said...

If you have to fix this stuff all day long then you should either get another job without so many lamers, or fire their asses because they should go back to college.

Brian Oxley said...

Whoever is making the obnoxious anonymous comments, would you just calm down a bit? There is nothing wrong with making mistakes, we all learn from them. And this post is not even a post about mistakes but introduces an alternative technique to the more common approach of getter methods. There is nothing wrong with getter methods; it is more a question of style.

Anonymous said...

Up until this point I have enjoyed the collegial nature of this BLOG and I would like to request that the individual posting obnoxious and useless comments please refrain from doing so. Your comments have become personal and no longer further the discussion.

Brian Oxley said...

Gee, I wish I had posted that! What a polite and polished way to make that request.

David Kemp said...

I agree that blindly following the rule that "all fields must be private" is not necessarily always good. However, the advantage of forcing access via a getter is that it gives you the option of changing its implementation at a later date: e.g. if one of the fields is a Date object, then you might later decide to encode it as a long and simply modify your getDate() method to convert back to a date. Your getters might also do de-compression or decryption etc. I know it goes against the "You Ain't Going To Need It" principal, but it is something to consider all the same.

Brian Oxley said...

David, I agree with you for business object as the getters may well represent potential behavior, be lazy-evaluated, etc.

But data transfer objects are, by definition, nothing more than data holders for communicating between program layers, so I am picturing public final fields as being like C-style structs but read-only.

Your point is good to remind me to apply this idea only to the realm for which it makes sense, and not to try and show off with a clever trick. Sometimes clever tricks are very seductive for me.