In this mini-Fragment episode, Donn talks about Item #14 of the Effective Java series – In public classes, use accessor methods, not public fields. You’ll learn why it’s important to use accessors in your public classes and some caveats to this rule.
For example, you may decide that the class is a private inner class or package private. Donn digs into the details in this week’s episode. This is a glimpse of what’s to come in Item #15, which is coming soon…
Donn Felker: Today, I’m going to talk about Item 14 in Effective
by Joshua Bloch.
For those of you who are just joining us, we do a small “mini-Fragment”
episode every once in a while. Some of these episodes are based around
Effective Java, a book that’s packed full of great information for
every single Java developer. It gives a bunch of patterns and practices
that you should implement in order to be a good Java developer. Our goal
here is to relate them to Android development, and to talk about each of
the items as we come across them.
Today, I’m talking about Item 14, which states: “In public classes, use
accessor methods, not public fields.” I think the key phrase here is “In
public classes…” Keep that in mind: Joshua is not talking about private
or package-private classes, but about public classes only.
Some folks are tempted to create data objects that, instead of having
accessors and mutators (getters and setters, respectively), just make
their fields public. They’ll make a public value, and they’ll just
access it that way. One of the reasons that this is looked upon badly by
some of the hard-line, object-oriented programmers is because it doesn’t
offer the benefits of encapsulation:
You can’t change the representation without changing the API, you
can’t enforce invariants, and you can’t take auxiliary action when a
field is accessed. Effective Java, page 71
There are a bunch of problems which you can encounter when you expose
these values as public fields.
On a personal note, I agree with him that when it comes to public
classes, which are accessible outside of their package, you should
provide some type of getter or accessor method. This allows you to
preserve some flexibility around that class’s internal representation.
If (for some reason) your class does expose a public field, all hope of
ever changing its representation is basically lost. That public
class—again, a public field or method—is a part of the API that you’re
giving. If you build a library and make something public, it’s going to
be used by people who are using your library. You need to think hard and
long about whether something should be public. If it’s a field, you’re
kind of tied to it. If you realize later (for some reason), “Ooh, I need
to change that because of these problems,” there will be all sorts of
folks who are using that public field.
Instead, you should probably think about encapsulating the field in some
type of accessor (i.e. a getter method), and that’s exactly what item 14
Effective Java then dives in, saying that the main reason for this
item (again) is to preserve the class’s internal representation of the
data and give you some flexibility in how it works (if you need to
Now, there is a flip side to this coin (which everyone probably has on
the tip of their tongue): if the class is package-private or within a
private nested class, there’s nothing inherently wrong about exposing
its data fields, assuming that they do a good job of describing any type
of data or abstraction provided by said class. The reason for this is
that it generates less visual clutter (i.e. you have less code lying
around) than the typical accessor method approach. I’m sure you’ve seen
this: if you have ten fields in your class, and then (for some reason)
you generate getters and setters using Android Studio or IntelliJ, your
class suddenly explodes from 15 lines of code to 30-50 lines of code,
and you have a larger set of code to maintain. So, if the class is
private or package-private, you can go ahead and set your fields to
One of the reasons why it’s okay to do this in a private or
package-private class is because the client code (your library, or
whatever) is tied to the class’s internal representation and the package
containing that class. If changing something in the class is desirable,
you can make that change without having to worry about what it will do
to the public API. You aren’t changing a method name, its signature, or
anything like that which could be a breaking change.
However, you still have to be careful about what you’re doing to the
data, since you could be changing what’s happening (against the users
expectations). If (for some reason) you’re changing a value when another
method is called, you need to (of course) notate that in your release
Please note that you’ve probably seen different classes in Java itself
that completely violate this advice—for instance, the
Point class and
Dimension class. Apparently, according to the book, some internals
Dimension class which are exposed create a serious performance
problem that’s still in Java today. I haven’t dug into this exact issue,
so this is just from Effective Java, but Joshua is explaining, “Look,
Java has actually suffered from this, and they’re realizing it too.”
He’s giving the advice to provide a public accessor method, which helps
you fix or alleviate some of the problems that existing Java classes
have run into.
There’s also another caveat to this (which a lot of the folks out who
are really into immutable data types are probably screaming at me right
now): while it’s never a good idea for a public class to expose fields
directly, it’s usually less harmful if those fields are immutable. You
can’t change the representation of that data because it’s immutable.
Suppose I have a class called
Time with two variables:
Minute. We could set those as
public final int Hour and
public final int Minute. We could then pass those values in when we
create an instance of the
Time class. So you would say
pass in the hour and the minute, and those public fields would then be
instantiated. There are no setter methods. These are
fields, so you cannot change them. In that case, the class guarantees
that each instance represents a valid time, and something will not be
In summary, item 14 states that public classes should never expose
mutable fields. Of course, there are some caveats to that, such as inner
private and package-private classes, and also if those fields are not
going to be mutable.
I really hope that this helps you. Please pay attention to the next item
(item 15), where we’re going to be talking about minimizing mutability.
This is a huge topic in Android right now, and we’ll talk about these in
the next Fragment.