Instance Variables and Instance Methods
A variable holding null does not refer to any object. Null is the actual value stored in the variable, so the variable is null, and it does not point to null.
Starting With a Prediction About null
Many programs store objects in variables, and one of the most common sources of runtime failure in Java involves a variable that holds null. Before learning the rules, it helps to test your intuition. The idea developed in this article is that a variable holding null is a variable whose value is null, and that this is not the same thing as a variable that points to something called null. The rest of the article rebuilds that idea from the variable's point of view and then shows what goes wrong when code treats a null variable as if it held an object.
What do you think happens?
Suppose a variable std of a class type holds null, and a program then tries to refer to the instance variable test1 through it. What do you expect to happen?
Reveal answer
Java throws a NullPointerException while the program runs.
Referring to instance variables or instance methods through a null variable is illegal. There is no object behind the variable, so there are no instance variables to refer to, and Java throws a NullPointerException at run time.
What a Variable Holds When It Is Null
Many learners picture a variable as an arrow that aims at something. When a variable has no object to aim at, they often imagine the arrow pointing at a special target called null. That picture feels natural, and it leads to a predictable set of errors later on.
The correct description is different. Null is an actual value. It is not a hidden pointer that leads somewhere else. A variable whose type is given by a class can hold a null reference, written in Java as the keyword null, and when it does, the variable itself holds that value. So we describe the variable as being null. The phrase 'points to null' is considered incorrect because it places null at the far end of an arrow, as if null were a place. Null is the content of the variable.
The difference between the two situations can be seen side by side. In one case, the variable holds a null reference, so there is no object behind it. In the other case, the variable holds a valid object reference, so it leads to an object that has its own instance variables. The diagram below lays these two cases next to each other.
When a Variable Can Hold null
A variable can hold null when its type is given by a class. You store null in it the same way you store any other value, by assigning null to it. Java also lets you test whether the variable currently holds null, by comparing the variable with the keyword null. The source uses the comparison std == null for this purpose.
- PlayerData is a class type, so std can hold a null reference
- Assigning null stores the keyword null as the value of std
- The comparison std == null tests whether std currently holds null
The test does not create an object or change the variable. It only reports what the variable currently holds. This matters because a program often needs to check first, and only use the variable when it holds a real object reference.
What Happens When a Null Variable Is Used
With a valid object reference, a program can refer to instance variables and instance methods through the variable. With a null reference, the same request has no target, because the object that would hold those instance variables does not exist. The source states the rule directly: if the value of a variable is null, it is illegal to refer to instance variables or instance methods through that variable, because there is no object and so no instance variables to refer to.
The trigger is specific. Suppose std is null. Writing std.test1 asks for an instance variable through a variable with no object behind it. Java treats this as an illegal request and throws a NullPointerException while the program runs. The flowchart below follows the decision Java makes when code reaches into an object through a variable.
NullPointerException- The assignment std = null is accepted without any error
- The failure appears on the line that uses std, not on the line where null was stored
- The useful debugging question is which variable held null at the point of use
When this error appears, trace the variable's value line by line. Find the last point where std was assigned, confirm whether that assignment stored null, and then check the line where std was used. The gap between the two lines is where the program diverged from what you expected.
Instance Variables Belong to Each Object
An object created from a class is an instance of that class, and the variables it contains are called instance variables. The word 'instance' names the object, so an instance variable is simply a variable that lives inside one particular object.
The key fact is where these variables live. Instance variables are part of the object, not part of the class. The class describes which variables an object will have, but the values belong to each individual object. This is why two objects created from the same class can hold different data at the same time.
The source illustrates this with a PlayerData class. When an object is created from it, that object is an instance of PlayerData, and the name and age variables are instance variables in that object. The example below is an original illustration of the same idea, with two objects built from one class.
- p1 and p2 are two separate instances of the PlayerData class
- The name and age instance variables exist in each object
- Setting p1.age does not change p2.age, because each object holds its own values
Instance Methods and Logical Containment
The same idea extends to behavior. The subroutines that an object contains are called instance methods. The source states that instance methods are the non-static methods, and that they become part of objects created from the class. Because an instance method is logically part of the object, you can think of the object as carrying its behavior along with its data. The object contains both its instance variables and its instance methods in this logical sense.
Many beginners picture object-oriented programming like a set of cookie cutters. The class is the cutter, and every object made from it is a full, independent copy of everything the class describes, including the behavior. Under that picture, if a class has an instance method and you create three objects from it, you would expect three separate copies of that method's code in memory, one inside each object.
The cookie cutter picture is a misconception. The mistake is taking the word 'contains' too literally. It is not literally true that each object contains its own copy of the compiled code for an instance method. The compiled code for a method is a single thing that the class defines. What each object has is a logical relationship to that method: the method is one of the things that belongs to the object, and the object is the thing you call the method on.
Static Methods Versus Instance Methods
Not every method belongs to objects. The source contrasts two kinds. Static methods are part of the class, and they are associated with the class, not with objects. Non-static methods, which are the instance methods, become part of objects created from the class. Keeping this contrast in mind prevents a common confusion about where a method lives.
| Feature | Static method | Instance method (non-static) |
|---|---|---|
| Belongs to | The class | Objects created from the class |
| Is it associated with objects? | No, it is associated with the class | Yes, it becomes part of each object |
| Logically part of | The class | Each object that the class creates |
| Stored code | A single definition owned by the class | A single definition owned by the class, logically shared by its objects |
| Typical question it answers | What does the class do as a whole? | What does this particular object do with its own data? |
Static and instance methods, as described in the source
Mistakes Learners Make With null and Instance Members
Common mistake Describing a null variable as pointing to null
What it looks likeSaying that std points to null, as if null were a destination
Why it failsNull is the actual value stored in the variable, so the variable is null. There is no object at the far end of an arrow.
Do this insteadSay that std holds null, and that there is no object behind it
Common mistake Expecting the error on the line that stores null
What it looks likeAssuming std = null fails immediately, and then being confused when a later line fails
Why it failsThe assignment of null is accepted. The failure happens on the line that refers to an instance variable or instance method through std.
Do this insteadLook for the line that uses the variable, and trace back to find which assignment stored null
Common mistake Using a null variable to reach an instance variable
What it looks likeWriting std.test1 when std holds null
Why it failsThe rule is that referring to instance variables or instance methods through a null variable is illegal, and Java throws a
NullPointerException.Do this insteadTest with std == null first, and only use std when it refers to a real object
Common mistake Believing each object stores its own copy of method code
What it looks likeImagining three objects of a class each holding a separate copy of an instance method
Why it failsThe source says it is not literally true that each object contains its own copy of the compiled code. The method is a single definition that the class provides.
Do this insteadThink of the method as logically belonging to each object, while its code is defined once
Common mistake Treating static methods as belonging to objects instead of the class
Checking Your Understanding With a Scenario
A program creates a PlayerData variable called std and assigns null to it. Later, the program refers to std.age. Trace the value of std line by line. At which line does the program fail, and what kind of exception does Java throw? Then describe, in your own words, what std holds at the moment of failure without using the phrase 'points to'.
Hints
- Ask what std holds after the assignment, not what it refers to
- Consider whether an object exists behind std at the moment age is requested
- Recall which exception Java throws when an instance member is reached through a null variable
Two PlayerData objects are created, p1 and p2. Change p1.name and confirm that p2.name is unaffected. Then explain why the instance variables can differ between the two objects, while the definition of the PlayerData class is shared by both.
Hints
- Instance variables are part of the object, not the class
- The class describes which variables an object will have, and the values belong to each object
Key Takeaways
- A variable holding null does not refer to any object. Null is the actual value stored in the variable, so the variable is null, and 'points to null' is the wrong description.
- Using a null variable to refer to an instance variable or instance method is illegal, and Java throws a
NullPointerExceptionwhile the program runs, at the line where the variable is used. - An object created from a class is an instance of that class. Its instance variables are part of the object, so each object holds its own values.
- Instance methods, the non-static methods, logically become part of each object, but it is not literally true that each object stores its own copy of the compiled code.
- Static methods are part of the class and are associated with the class, not with objects.