Concepts / Private Instance Variables

Private Instance Variables

A setter method is the controlled way for other classes to change a private variable, and every change should pass through it.

  • Programming

Why Private Fields Need a Gatekeeper

A class often keeps its data in private variables so that code outside the class cannot change them directly. That protection only helps if the class still offers a legitimate way to change the data. A setter method is that way. It is an ordinary method whose job is to store a new value into a private variable on behalf of some other class. Because every change passes through one method, the class has a single place where it can decide whether a change should be allowed.

This article follows a code-first path. You will look at a small setter, predict what it does with an unusual input, and then work out the mechanism that produces the result. Pay attention to the moment the value moves from the parameter into the private variable, because that moment is where both the normal behaviour and the validation logic live.

What do you think happens?

A setter for a title field has a check that replaces null with the default (Untitled). If the caller passes null, what does the field hold afterwards?

  • null

  • An empty string

  • (Untitled)

Reveal answer
Answer:

(Untitled)

The validated setter tests the incoming value. A null argument takes the branch that stores the default, so the field ends up holding (Untitled) rather than null. Keeping null out of the field is the purpose of validation.

Private Fields and the Setter Route

Making a field private means outside code cannot assign to it directly. The field still exists, and the class itself can use it, but any other class that wants a new value must ask the class to store it. The setter is that request channel. Every path that changes the field runs through the setter body, and that is why the body is the correct place to put a check. A check placed anywhere else would leave a second route by which a bad value could reach the field, which would defeat the purpose of making the variable private.

Naming and Parameter Conventions

A setter has two conventions that tell other programmers what it does. The first is its name. The name begins with the word set, followed by a copy of the variable's name with its first letter capitalized. A variable called title therefore gets a setter called setTitle. The second convention is the parameter. A setter takes one parameter whose type matches the type of the variable it sets. For a String field, the parameter is a String. Following these two rules makes the setter easy to find and easy to use correctly.

java
Notes on the code
  • private String title: the field is hidden from outside code
  • setTitle: the name is set plus the field name with a capital letter
  • String title parameter: the type matches the field type
  • this.title = title: the parameter is copied into the private field
public voida method that returnsnothingsetTitleset plus TitleString titleparameter type matchesfield typethis.title = titleparameter copied intoprivate field
How do the parts of a setter's signature (name, parameter, assignment) correspond to the private variable it controls?

Tracing a Setter Call

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 shows the three participants involved and the order of their messages. The caller never touches the field itself.

Calling codethe line that asks for achangesetTitle bodythe only route to the fieldtitle fieldprivate storage1. call setTitle(value)2. parameter assigned to title3. body ends, control returns
What happens, step by step, from the caller's line of code to the private field being assigned a new value?
  1. 1
    The calling code names the setter and passes a value, for example setTitle with the text Dune.
  2. 2
    Control leaves the caller and enters the setter.
  3. 3
    The passed value is bound to the parameter called title.
  4. 4
    The setter body runs. Its assignment copies the parameter into the private field.
  5. 5
    Control returns to the caller. The field now holds the new value.

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 keeps null and other invalid values out of private variables, so the rest of the class can rely on the field holding something usable.

java
Notes on the code
  • The test title == null is the validation check
  • The first branch stores the safe default
  • The second branch stores the value unchanged

The validated version has two branches, but only one runs for any given call. A null argument takes the first branch and stores the default. Any other argument takes the second branch and stores the value unchanged. The method always ends with the field holding a value, which is the property the unchecked version lacked.

Incoming valuepassed to the parameterIs value null?validation checkStore (Untitled)safe defaultField holds a valuenever nullStore value unchangedlegal valueyesno
Which path does an invalid value take through the setter, and at what point is it swapped for the default before being stored?

Tracing a Null Input Through the Setter

Worked example

Calling setTitle with null

The field title currently holds Dune. The caller runs book.setTitle(null). What does the field hold afterwards, and which branch decides it?

  1. 1
    Start state

    The private field title holds Dune before the call.

  2. 2
    Bind the parameter

    The argument null is bound to the parameter title. The field has not changed yet.

  3. 3
    Run the check

    The test title == null is true, so control takes the first branch.

  4. 4
    Store the default

    The branch assigns (Untitled) to this.title. The value Dune is overwritten.

  5. 5
    Return

    The setter finishes and control returns to the caller. The field holds (Untitled).

Result

The field title now holds (Untitled). Null never reaches the field.

Before
book.setTitle("Dune");

title holds Dune

After
book.setTitle(null);

title holds (Untitled)

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 shows where to look.

  1. 1
    Confirm the setter was called. If the field is unchanged, the call may never have run.
  2. 2
    Check the value that reached the parameter. The argument at the call site may differ from what you expected.
  3. 3
    Check which branch the validation took. A check that tests the wrong condition sends a legal value to the default, or an illegal one past the check.
  4. 4
    Check what the assignment stored. Compare the value that the chosen branch wrote with the value you expected it to write.

Key Takeaways

  • A setter is the controlled way for other classes to change a private variable, and every change should pass through it.
  • A setter is named set plus the variable name with a capital first letter, and its single parameter has the same type as the variable.
  • Calling a setter moves control into its body, where the parameter is assigned to the private field before control returns to the caller.
  • Validation checks the incoming value and stores a safe default, such as (Untitled), when the value is invalid, which keeps null out of the field.
  • When a stored value looks wrong, trace backwards from the variable: the call, the parameter value, the branch taken, and the assignment.