I often hear the opinion that writing getters and setters has
something to do with better encapsulation, that using “naked” fields is
bad practice. To find out if this is true, we have to look at Java
history. In the mid-nineties, Sun developed the Java Bean Specification
as a component model for Java. This model was supposed to help with
tool support for Java, e.g. when connecting a graphical user interface
with domain objects. In this case, it is useful if one can observe
changes made to fields and react to them (e.g. by updating the text
displayed in a window). Alas, while there are some languages that allow
this kind of meta-control (Python and Common Lisp come to mind), Java
does not. Thus, Java Beans introduced standardized naming that allowed
one to implement a field as a pair of methods which then would manually
implement the observation.
I usually code as follows: If I need just a field, I use a public field (no getters and setters), because it helps me to get started quickly and introduces less clutter. If I later change my mind, I let Eclipse introduce the indirection of the getter and setter. That means that there is no penalty for such a change and no need to think ahead! Granted, having both public fields and getters/setters affects uniformity, but the added agility is worth it for me.
Obviously, it would be nice if Java had true observable (and optionally computable) fields. This feature was initially on the table for Java 7, but did not make the cut. Maybe IDEs could help by displaying getters and setters as if they were fields. Their source code would be hidden, with visual clues indicating if such a pseudo-field is read-only etc. Additionally, auto-expansion would be improved, because pseudo-getters (such as Collection.size()), getters/setters, and fields would all be part of the same category. No more typing “.get” and hoping that the information that you are looking for is available as a properly named getter. The same kind of grouping should also be made in JavaDoc. Lastly, one could display foo.setValue("abc") as foo.value = "abc". But I’m not sure if that makes sense.