Concepts / Instance Methods and Object State

Instance Methods and Object State

An instance variable can receive an initial value directly in its declaration, such as public int die1 = 3;, and that value is the starting value of each new object.

  • Programming

Why a New Object Already Holds Values

Every object you create begins its life with some values stored in its fields. Consider a program that models a pair of dice. Each pair needs two numbers, one for each die, and those numbers must already have a value the moment the pair exists. Someone reading the class needs to know what those starting values are, and so does anyone debugging a program that seems to show the wrong number.

This article follows one class from its source code through to the values an object actually holds, and it shows where those values come from. The answer comes straight from the declarations. Before you read on, make a prediction about the simplest case, where a field is declared with no value at all.

What do you think happens?

A class contains the declaration public int die1; with no initializer. What value does die1 hold in a newly created object?

  • 0

  • 1

  • 3

  • null

Reveal answer
Answer:

0

When a declaration has no initializer, Java supplies a default value based on the variable's type. For an int, which is a numeric type, the default is zero.

Tracing the Starting State of PairOfDice

Start by reading the class itself. The statement public int die1 = 3; declares an instance variable named die1 that holds an int, and it fixes that variable's starting value at 3. The declaration has the same form as any other variable declaration: you write the type, the name, an equals sign, and the starting value. Because the value is part of the declaration, a reader can see the starting state of the field without searching through the constructor or other methods.

java

Trace what happens when someone writes new PairOfDice(). The new object is created, and each field receives the value named in its declaration: die1 holds 3 and die2 holds 4. Nothing in the class changes those values until a method assigns something new to them. The roll() method is the only code in this class that does so, and it runs only when someone calls it. So immediately after creation, the object's state is die1 = 3 and die2 = 4, and it stays that way until roll() is called.

How Initializers Set Starting Values

An initializer is the part of a declaration after the equals sign. It is the value the field holds when the object is created. You can think of it as a rule that runs as part of creation rather than as a line of code that runs later. The same two fields can be written with or without initializers, and the difference shows up only in their starting values. The field names and types stay the same.

new object createdDeclaration has aninitializer?Use the declaredvaluefor example 3 in int die1 =3Field holds itsstarting valueUse Java's defaultfor the typefor example 0 for int withno initializerfor each fieldyesno
When a new object is created, does each instance variable start with its declared initializer or with Java's default for its type? Follow the check for each field.

The diagram shows the decision Java makes for each instance variable. If the declaration includes an initializer, that value is used. If it does not, Java supplies the default for the variable's type. The diagram describes the same two fields in two versions of a class: in one version neither field has a declared value, so each receives its default, and in the other the initializers replace those defaults with 3 and 4.

Tracing Defaults When No Initializer Is Written

A declaration does not have to include an initializer. If you leave one out, Java still gives the instance variable a starting value automatically, and the value depends on the variable's type. The default values are zero for numeric types, false for boolean, the Unicode character with code number zero for char, and null for object types. String is an object type, so a String field begins as null, not as an empty string.

The rules in the map are the ones to memorize. Numeric types such as int and double start at zero. A boolean starts at false. A char starts at the zero-code character, and a variable of object type starts at null. Notice that the default depends only on the type of the field, not on anything else in the class.

java
Output
0
0.0
false
0
null
Notes on the code
  • count has no initializer, so it starts at 0
  • price is a double with no initializer, so it starts at 0.0
  • ready is a boolean, so it starts at false
  • The char is cast to int to show its numeric code, which is zero
  • label is a String, an object type, so it starts at null rather than an empty string

The cast on the char line is there for readability. A raw zero-code character would be hard to read on screen, so casting it to int shows its numeric code, which is 0. The output lines match the default rules: 0 for the numeric field, false for the boolean, the zero-code character for the char, and null for the String.

Worked example

Mixing an Initializer With a Default

A class declares public int die1 = 3; and public int die2; with no initializer. What are the starting values of die1 and die2 in a newly created object?

  1. 1
    Check die1

    The declaration includes the initializer 3, so the declared value is used. die1 starts at 3.

  2. 2
    Check die2

    The declaration has no initializer. Because int is a numeric type, Java supplies the default zero. die2 starts at 0.

  3. 3
    Confirm the moment

    Both values are set when the object is created. Neither changes until a method assigns a new value.

Result

die1 starts at 3 and die2 starts at 0.

Mistakes When Reading Starting Values

  • Common mistake

    Assuming a String field starts as an empty string

    What it looks like
    public String label; followed by label.length() on a new object
    Why it fails

    A String is an object type, so a field with no initializer starts at null. Calling a method on null causes an error rather than returning 0.

    Do this instead

    Read the declaration. If there is no initializer, expect null and check for it before using the field.

  • Common mistake

    Assuming every field starts at zero

    What it looks like

    Reading a boolean field with no initializer and expecting 0

    Why it fails

    The default depends on the type. A boolean starts at false, a char starts at the zero-code character, and an object type starts at null.

    Do this instead

    Look up the default for the field's own type rather than applying one rule to every field.

  • Common mistake

    Thinking the initializer runs once for the whole class

    What it looks like

    Expecting a second PairOfDice to keep the values changed in the first one

    Why it fails

    Instance variable initialization runs for every new object, so each object gets its own starting values. Only static variables are initialized once, when the class is first loaded.

    Do this instead

    Treat each object as having its own fields, and check the declaration for each new object rather than assuming a shared value.

  • Common mistake

    Blaming the wrong moment when a value looks wrong

    What it looks like

    A die shows 5 right after creation and the reader assumes the initializer is broken

    Why it fails

    Initialization belongs to the moment the object begins. A value that changes later usually came from an assignment inside a method, such as roll().

    Do this instead

    Ask which moment produced the value. If the declaration has an initializer, check whether a later assignment changed it before the value was read.

Checking the Starting State

EASY

A class declares public int die1 = 3; public int die2; public String name; and public boolean active;. Without running the code, write down the starting value of each field in a newly created object. Then say which field's value comes from an initializer and which comes from a default.

Hints
  • Check each declaration for an equals sign. If there is one, the value after it is the starting value.
  • For fields without an initializer, look up the default for the type: 0 for int, false for boolean, and null for String.
  • Remember that name is an object type, so its default is null, not an empty string.

Where Starting Values Come From

When an object is created, each instance variable receives a starting value. If its declaration has an initializer, that value is used. If not, Java supplies a default based on the type. Those starting values are kept separately for each object, and they remain until a method assigns something new.

Key Takeaways

  • An initializer in a declaration, such as public int die1 = 3;, sets the starting value of that instance variable for each new object.
  • Without an initializer, Java supplies zero for numeric types, false for boolean, the zero-code character for char, and null for object types including String.
  • Initialization runs for every new object, so each object has its own fields; static variables are initialized once when the class is first loaded.
  • When a value looks wrong, check whether the declaration has an initializer and whether a later assignment in a method changed it before it was read.