Accessors and Mutators

Getters (also called accessors) and setters (also called mutators) are a fundamental approach to abstraction. This article explains the purpose of getters and setters, and how they are used in Java.

What are they?

It is quite common to find examples, both online and in the literature of classes, of private instance variables with public methods for accessing the values of the variables and public methods for re-setting the values of the variables.

A method for accessing the value of a (potentially private) instance variable is called an accessor method, and a method for changing the value of a (potentially private) instance variable is called a mutator method. Often the examples give the accessor methods the name getVariableName() and the mutator methods the name setVariableName() (where "VariableName" is the name of the (potentially private) instance variable. Therefore, mutators are often also called setters, and accessors are often called getters.

An example could be:

public class Time {
  private int hour;
  private int minute;
  private int second;

  public Time( int h, int m, int s ) {
    hour = h;
    minute = m;
    second = s;
  }

  // set the hour
  public void setHour( int h ) {
    hour = ( ( h >= 0 && h < 24 ) ? h : 0 );
  }


  public void setMinute( int m ) {
    minute = ( ( m >= 0 && m < 60 ) ? m : 0 );
  }

  public void setSecond( int s ) {
    second = ( ( s >= 0 && s < 60 ) ? s : 0 );
  }

  // Get Methods
  // get the hour
  public int getHour() { return hour; }
  
  // get the minute
  public int getMinute() { return minute; }

  // get the second
  public int getSecond() { return second; }

}

As a comment to the class above, think about an alternative Time class where second, minute, and hour are public but they are also final (can't be re-assigned). If we remove the accessors and mutators from the class and do the validation in the constructor, having the final instance fields declared public is actually not a problem in terms of keeping the class invariant (the promise that we will always ever have a valid time). The constructor would typically throw an IllegalArgumentException (a runtime exception) if the caller violates the invariant (the rule that second and minute must be between 0 and 59 and that hour must be between 0 and 23). This behavior of the constructor (throwing an exception if it finds a violation) guarantees that there can never exist a Time object with a faulty state (an invalid time with for instance hour set to 25 or something stupid like that).

So the problem with the argument we often see together with examples of getters and setters, that "they are (the only) way to guarantee that wrong values can never enter the object". This is, as you now see, not true at all. Even public fields (if they are final) can be guaranteed to hold the class invariant through the lifetime of the object (if the constructor throws an exception rejecting violations). Not only that, with public variables there is no need for accessors or mutators.

We don't recommend public instance variables (even final ones), however, but the above proves a point about the faulty reasoning behind mutators as the (only) way to guarantee invariants (check and verify values which must be valid according to some rules).

 

Doesn't every class have them?

No, not every class has getters and setters. Particularly, not every class has getters and setters. Even more particularly, not every class has getters and setters for every private instance variable!

The point we are trying to convey is that you should think about what you do, what you read, and what you hear. If you get the idea from somewhere that you should always make public getters and setters for your class' private instance variables, you should stop and think about why you would want that.

Granted, the setters from the example above are an improvement over public instance variables because you can check that the value passed to the setters makes sense – you shouldn't allow the second value of time to be greater than 59, for instance. The setter guarantees that (similar checks could be done in the constructor!).

But what you should think about is, once a Time object is created, do you really need a way to programmatically change the variables for second, minute, and hour separately? Do I really want a Time object to be changed at all? Perhaps the only way for a Time object to change should be by some other means, like ticking (increasing) a certain amount of seconds and letting that reflect on the other variables. Who knows, but it certainly merits thinking about.

We try to convince you here, that there is no automatic need for getters and setters for every private variable in every class.

There are many classes in the Java API that do not have getters and setters for the private instance variables. Some classes do not have any setters at all, in fact. Instead, some classes provide instance methods that create a completely new object of the class if someone wants to change what an object represents.

To take a few examples of classes that lack getters and setters from the Java API, we could look at java.io.File. The File class represent file and directory paths. It declares the following private instance variables:

   private final String path;
    private transient PathStatus status = null;
    private final transient int prefixLength;
    private volatile transient Path filePath;

But it does not declare the following getters:

getFilePath()
getPrefixLength()

From this we can realize that there is no rule that every private variable must have an accessor with a name starting with get followed by the variable name. In fact, there is no rule that every private variable must have an accessor method with any name at all.

The File class declares the following methods with a name starting with set:

    public boolean setLastModified(long time)
    public boolean setReadOnly()
    public boolean setWritable(boolean writable, boolean ownerOnly)
    public boolean setWritable(boolean writable)
    public boolean setReadable(boolean readable, boolean ownerOnly)
    public boolean setReadable(boolean readable)
    public boolean setExecutable(boolean executable, boolean ownerOnly)
    public boolean setExecutable(boolean executable)

As you can see, none of the methods named set-something has any of the private variables' names as part of its name. From this, we can learn that there is no rule that every private variable must have a mutator called set and the variable name as the rest of the method name. In fact, there is no rule that every private variable must have a mutator method with any name at all.

We can say that there is at least one class in the Java API whose private variables lack a getter and setter. In fact, this holds for most classes in the API.

The File class has been around in the Java API for quite some time.

 

Where do they come from?

Why do books and resources insist on showing classes where every single private instance variable has a corresponding getter and setter method? We have no idea. We suspect it is some kind of not-so-well-founded consensus based on some kind of feedback loop. We haven't tracked down the source of this idea, but we've seen it propagate to numerous books and online examples (including even some examples on Oracle.com).

It is not that we hate the idea, just that we do not like that such resources might give the readers the idea that this is a rule or something that you should do without hesitation. It is the knee-jerk reaction of writing getters and setters for every private variable we object to. If you have good reasons to provide both getters and setters, then there is no compelling argument (or consensus) for naming them exactly getVariable() and setVariable(). There might be much better names, in fact. But this is a matter of style and preferences. There is, however, no rule for having getters and setters or for what to name them if you choose to have them.

We have some theories as to where this comes from. One theory involves a standard for creating a certain type of class for a certain type of object called JavaBeans. In this standard, there is a rule (for technical reasons which have to do with dynamically creating classes and objects) that every private instance variable must have a corresponding getter and setter. But this standard should be seen, in our humble opinion, as an exception and not as a general rule for all the classes in the world.

Another theory we have is that some applications used for creating Java programs (IDEs) add code for getters and setters automatically when you create private instance variables. Why they do this is beyond our comprehension.

You may choose to include accessors and mutators in all your classes if you think it is a compelling idea which adds to the safety and usability of your classes. Just try to remember that this idea is not shared by every author of every book about Java.

 

What could the problems with them be?

If you think about it, the idea of having access modifiers such as public and private is to hide implementation details behind those that are private and provide useful abstractions via what is public. If we make public getters and setters (especially if the getters and setters have exactly the same type as the private variable) we actually "leak" implementation details of the types for our private variables. We create a coupling between our choice of type (and even our name if you follow the crazy idea of the getters and setters "naming convention" to the letter) for our private variables and the users of our classes.

If we later decide to change the name or type of a private instance variable (which should remain an implementation idea), what should you do with the getters and setters? Change their signatures? Change the getters return type? Of course, you could keep the old version of the getters and setters and use type conversion (cast) between the old type and the new type of the private instance variable. But if you do, you are violating the idea of the getters and setters to reflect the name and type of the private variables. So this also proves that such an idea or convention is at least not future proof.

As we hinted above, quite a few classes do not even allow modification of the internal state of the object via methods. They instead return new objects if some client code (user of the class and objects) wants a new state reflected. There are many reasons why this is a good idea. If you accept that, for instance, String, Integer, Double, and many more classes are implemented like this, that at least shows that there cannot be a rule to provide mutators for every (or even any) private instance method.

What could we use instead, then? Put simply, you can set an object's initial state (set the private instance variables reflecting the state of the object) via parameters to the constructor, and only provide accessors for the values users of your class might need. If there is a need for changing some parts of the state, you can choose between making a mutator (with any name you like), or make the class immutable and instead return a reference to a new object of the same class which reflects the new state.

There are times when you definitely could argue for a getter or even a setter, but this should not be something you provide every private variable without thinking or seeing a strong need for (as with any public method).

Another problem even with accessors (getters) is that they can expose a mutable instance variable that is meant to be private and never changed (not even with a mutator/setter). Consider having a private ArrayList as an instance variable, and that this list is very sensitive and should not be changed by outsiders (people using your class). It is not enough to not write a mutator for this variable, because it is a reference variable. If you have an accessor (getter) that returns this private reference variable, you are returning a reference to the actual ArrayList object, and ArrayLists are inherently mutable.

Someone could then do this in order to add an entry to the list, using only the accessor (getter):

objectRef.getList().add(aNewObjectReference);

In order to prevent such outrageous behavior, we must make sure that either the array list isn't mutable (it is not possible to add new elements to it), or rather return a reference to a copy of the list from the accessor (getter).

 

Summary

  • You don't have to write accessors and mutators for every private instance variable
  • The constructor works fine for setting the values of an object once and for all
  • If you want to write accessors and mutators, you should have already thought about why
  • If you want to write accessors and mutators, you do not have to use the prefices get and set for the names of these methods
  • Mutators (or setters as they sometimes are called) are not the only way to prevent bad values entering an object's state
  • The constructor can validate values and abort the construction of the object by throwing an exception

Source: Rikard Fröberg and Henrik Sandklef, http://wiki.juneday.se/mediawiki/index.php/Getters_and_Setters
Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License.

Last modified: Thursday, October 1, 2020, 2:17 PM