Concepts / Implementing Setter Methods

Implementing Setter Methods

A getter method provides read access to a variable by returning its current value to the caller.

  • Programming

A Book That Guards Its Title

Imagine a class that stores information about a book. The class keeps the book's title inside a member variable. Other parts of a program often need to know that title, but they should not have to reach into the class and grab the variable directly. Instead, the class can offer methods that control how the variable is read and how it is changed. This article covers the two most common of those methods: the getter, which hands a value out, and the setter, which accepts a new value and stores it.

Keep the book example in mind as you read. The goal is to see how a method can give other code a way to read a variable's value, how the method is named, how a setter takes a new value in, and where things commonly go wrong when you write one yourself.

What do you think happens?

A class has a title field that was set when the object was created. A caller asks the class for the title through a getter. What does the caller receive?

Reveal answer
Answer:

The caller receives the value the title field holds at the moment the getter runs.

The getter does not return a copy of some saved default or a value from earlier. It reads the variable as it is right now and returns that value. Because a getter only reads, the value the caller receives is simply whatever the field contains at that instant.

Reading a Value Through a Getter

Definition

A getter method is a method whose purpose is to return the current value of a variable. Because it only passes a value out, programmers describe it as providing read access to that variable. The method reads the variable on behalf of the caller and returns what it finds there.

Think of a getter as a window for looking at a value. The caller receives the value the variable holds at the moment the method runs. When you read a getter, treat it as a question the caller asks and the class answers with the stored value. Calling a getter does not change the stored value. It only reads it.

java
Notes on the code
  • The field title is private, so code outside the class cannot read or change it directly.
  • getTitle is public, so any caller can ask for the title.
  • The return type String matches the type of the field it reads.
  • The body only returns the stored value; it never assigns to title.
Worked example

Tracing a getter call

A Book object was created with the title Dune. The caller runs the statement String result = book.getTitle(); What value ends up in result?

  1. 1
    Create the object

    The constructor assigns Dune to the private field title.

  2. 2
    Call the getter

    The caller invokes getTitle(). Control moves into the method body.

  3. 3
    Read the field

    The method body reads the current value of title, which is Dune.

  4. 4
    Return the value

    The value flows back out through the return and is assigned to result. The field itself is unchanged.

Result

result holds Dune, and title still holds Dune afterward.

Naming Getters and Setters

Java programmers follow a naming convention for getters. The name is not chosen freely. It is derived from the variable it reads, so that anyone who knows the variable's name can guess the getter's name. The derivation has two mechanical steps that you can apply to any variable: capitalize the first letter of the variable's name, then place get in front of it.

getfixed prefix by conventionTitlevariable title with firstletter capitalizedjoined to form getTitle
How the variable name title maps to the getter name getTitle. The word get is fixed by convention, and only the capitalized variable name changes from one variable to the next.

The same convention governs setters. A setter's name begins with the word set, followed by the capitalized variable name. A variable called title therefore gets a setter called setTitle. The setter also has a parameter whose type matches the type of the variable it sets. For a String field, the parameter is a String.

Changing the prefix in one of these names is what the convention is designed to prevent. Following the two rules, the name prefix and the matching parameter type, makes the setter easy to find and easy to use correctly.

Tracing a Setter Call

Consider a class with a private String field named title and a setter that does nothing except copy the incoming value into the field. The setter is written like this:

java
Notes on the code
  • The name setTitle follows the set-plus-capitalized-variable rule.
  • The parameter title is a String, matching the type of the field.
  • The assignment this.title = title copies the parameter into the private field.

When calling code writes a new value through a setter, control leaves the caller and enters the setter. The value passed in is bound to the parameter. The setter then performs its body, and the body is what reaches the private variable. Control returns to the caller once the body finishes. The diagram below shows the participants involved and the order of their messages.

Callercode calling obj.setTitleSetter parameterincoming value bound hereValidation checkis the value legal?title fieldprivate member variable1. passes value2. value is checked3. stored in field4. control returns
In what order do the caller, the setter's parameter, the validation check, and the private field interact when a setter is called? The caller sends the value, the parameter receives it, the check decides what gets stored, and the field is the last participant to change.

The reason setters exist is protection. A class often keeps its data in private variables so that code outside the class cannot change them directly. That protection is only useful if the class still offers a legitimate way to change the data. A setter provides that way. Because all changes pass through one method, the class has a single place to decide whether a change should be allowed.

Adding Validation with a Safe Default

Validation means checking a new value before it is assigned to the private variable. The check decides whether the value is legal. When the value is not legal, the setter does not store it as given. Instead, it stores a default value that the class considers acceptable. Validation can keep null and other invalid values out of private variables, so that the rest of the class can rely on the field holding something usable.

java
Notes on the code
  • The null check is the validation step: it tests whether the incoming value is invalid.
  • The first branch stores the safe default (Untitled) instead of null.
  • The second branch stores the value unchanged, since it passed the check.
  • Only one branch runs per call, and the field always ends up holding a value.
Incoming valueargument to setTitleIs value null?validation checkUse (Untitled)safe defaultAssign to title fieldfield always holds a valueUse value as givenvalue passed the checkyesno
Which path does the incoming value take through the setter? It is either stored as given or replaced by the default when it fails the null check, and the two branches rejoin at the point where the field is assigned.
Before
public void setTitle(String title) {
    this.title = title;
}

Passing null stores null in title, so later code may receive an unusable field.

After
public void setTitle(String title) {
    if (title == null) {
        this.title = "(Untitled)";
    } else {
        this.title = title;
    }
}

Passing null stores (Untitled) in title, and any other value is stored unchanged.

Finding Where a Result Diverges

When a setter seems to store the wrong value, the fastest way to find the fault is to ask which line produced the stored value. Start from the variable and work backwards. Ask whether the setter was called at all, which value reached the parameter, which branch the check took, and what the assignment stored. A mismatch at any of these points tells you where to look.

Worked example

Locating a divergence in a validated setter

The caller runs book.setTitle(null) and then prints book.getTitle(). The caller expected null to be printed, but the output is (Untitled). Where does the stored value diverge from the expected result?

  1. 1
    Check the call

    setTitle was called with null, so the value reached the parameter as the caller intended.

  2. 2
    Check the branch

    The condition title == null is true, so the first branch runs.

  3. 3
    Check the assignment

    The first branch assigns (Untitled) to the field. This is the point where the stored value stops matching the caller's value.

  4. 4
    Compare with the getter

    getTitle reads the field and returns (Untitled). The getter is not the fault; it faithfully returns what the setter stored.

Result

The divergence is at the assignment inside the null branch. The behaviour is the validation working as designed, not a bug, but the caller must know that null is replaced by the default.

Mistakes with Getters and Setters

The following mistakes come up often when people first write getters and setters. Each one breaks either the naming convention or the single-gate idea that makes setters useful.

  • Common mistake

    Naming a setter without the set prefix or with a lowercase variable name

    What it looks like
    void title(String title) or void settitle(String title)
    Why it fails

    The convention is that the name begins with set followed by the capitalized variable name, so other programmers and tools cannot find the setter by the rule.

    Do this instead

    Use setTitle for the variable title.

  • Common mistake

    Using get for a boolean getter

    What it looks like
    public boolean getDone()
    Why it fails

    For boolean variables the is prefix replaces get, so the expected name is isDone.

    Do this instead
    Write public boolean isDone().
  • Common mistake

    Giving the setter a parameter type that does not match the field

    What it looks like
    private String title with void setTitle(int title)
    Why it fails

    The parameter should have the same type as the variable it sets, so the value passed in cannot be stored without conversion.

    Do this instead

    Declare the parameter as String to match the field.

  • Common mistake

    Assuming a getter changes the variable

    What it looks like

    getTitle() that also resets title to a default

    Why it fails

    A getter only reads the variable; calling it does not change the stored value.

    Do this instead

    Keep the getter body to a read and a return.

  • Common mistake

    Writing to a private field from outside the setter

    Why it fails

    If a value can reach the field by a route other than the setter body, the validation placed in the setter is bypassed.

    Do this instead

    Route every change through the setter so that the single check always runs.

Practice Tracing a Setter

MEDIUM

A class has a private String field named title and the validated setter shown earlier. Trace the call book.setTitle(null) followed by book.setTitle(Emma) and then book.getTitle(). What does getTitle return, and at which step does the stored value differ from the first value passed in?

Hints
  • Work through each call in order, and track what the field holds after each one.
  • Ask which branch of the null check runs for each call.
  • getTitle only reads the field, so its result equals the last value stored.
EASY

Write a getter named isActive for a private boolean field named active, and a setter named setActive that takes a boolean parameter and stores it directly. Then state which method the caller should use to read the flag.

Hints
  • The boolean getter uses the is prefix in place of get.
  • The setter parameter type must match the boolean field type.

Key Takeaways

  • A getter provides read access to a variable by returning its current value, and calling it does not change the stored value.
  • Getter names are derived from the variable name: get plus the capitalized name, or is plus the capitalized name for a boolean.
  • A setter is the controlled way to change a private variable; its name begins with set, and its parameter type matches the field.
  • Every change passes through the setter body, so validation placed there can replace an invalid value such as null with a safe default before it is stored.
  • When a stored value looks wrong, trace backwards from the variable to the setter call, the parameter value, the branch taken, and the assignment.