Skip to main content
Logo image

Section 8.2 Instance variables

Another metaphor for classes that can help us understand the purpose of defining instance variables is to think of a class as like a blueprint for a house. The blueprint is not a house but it defines the structure of a house and if we build two houses from the same blueprint they will each be different houses but they will have the same attributes. If the blueprint says there’s a bathroom on the second floor, then both houses will have a bathroom on the second floor. In this analogy, the blueprint is like the class and the actual houses are the objects.
Figure 8.2.1. Using a blueprint (class) to construct houses (objects)
And to extend the analogy, the instance variables declared in a class are like the rooms in a blueprint; they lay out the structure of the objects made from that class. In our Person class from the previous section, we know that every instance of that class will have one String reference and one int value in its object data in memory.
This video explains the relationship between classes and instances and their attributes using a class Belt.
Figure 8.2.2. Belt Object Attributes
Now let’s look at some of the details of using instance variables such as how to refer to them, how they interact with other variables, and what private means.

Subsection 8.2.1 Referring to instance variables

As we saw in the previous section, instance variables declared in a class can be used by code elsewhere in the class. For instance the canVote method refers to the age variable.
public boolean canVote() {
  return age >= 18;
}
Even though age is neither a parameter nor a local variable declared in canVote we can refer to it to access the value of the instance variable, getting the value stored in the object data of whatever object we called canVote on.
But sometimes we need to access an instance variable of another object. For example the greet method needs to get the name of the other Person:
public void greet(Person other) {
  System.out.println("Hello " + other.name + ", I'm " + name + ".");
}
The code in the System.out.println line refers to both name and other.name. Just plain name refers to the instance variable in whatever object we called greet on. But other.name means get the instance variable from the object referenced by other, in this case the argument that was passed to greet. The dot in other.name is called the dot operator as we firs saw in Section 3.2 APIs and Libraries.
But what happens if a method or constructor has a parameter with the same name as an instance variable? For instance we saw this in the Person constructor where the constructor signature was:
public Person(String name, int age) {
Should plain name refer to the parameter holding the argument passed to the constructor or the instance variable? The rule in Java is it refers to the parameter. This is called shadowing; when two variables have the same name, one of them shadows the other. In methods and constructors, local variables, including parameters, shadow instance variables.
However, even when an instance variable is shadowed, we can refer to it using the dot operator and the keyword this as we saw in the code of the Person constructor.
public Person(String name, int age) {
    this.name = name;
    this.age = age;
}
The keyword this is kind of like a variable that exists without being declared in the body of all constructors and instance methods and whose value is always a reference to the the object being constructed or the object an instance method was invoked on. Because it’s a keyword we can’t use it as the name of a variable ourselves so it can’t be shadowed. That guarantees that this.name is always a reference to the instance variable name on the current object.
The idiom this.x = x is commonly used in constructors like the one above so that we can use the same name for parameters as the instance variables they are going to be assigned to. Some programmers prefer to use different, often shorter, names for parameters to avoid having to use this but that just means they have to come up with twice as many names. It’s simpler and idiomatic to use the same name and to disambiguate with this.

Note 8.2.3.

It is legal to use this and the dot operator to access an instance variable even if it is not shadowed but usually Java programmers don’t. Some other languages such as Javascript and Python always require a this. (Javascript) or self. (Python) to access instance variables so if you’ve used those languages you may be in the habit of always using them.

Activity 8.2.1. Spellcheck.

You do need to watch out that you don’t misspell your parameter names. In this constructor the instance variable name is not set to the argument passed to the constructor. Can you see why?
public Person(String nam, int age) {
    this.name = name;
    this.age = age;
}
Answer.
Did you notice that the first parameter spelled nam instead of name?
As a result in the line this.name = name both this.name and name refer to the instance variable so this line just assigns the current value (which will be null) back to the variable. It could just as well have been written name = name since there is no parameter shadowing it. Hopefully it’s obvious that that does nothing.

Subsection 8.2.2 The dreaded NullPointerException

There is, however, one other requirement for accessing an instance variable: we actually have to have an object. You may recall from Section 6.1 Creating and using arrays where we met our first reference type, that Java has a special reference value, null, which represents the absence of an object. That is, if a normal reference points to some object’s data somewhere in memory, the null reference is a special value that doesn’t point to anywhere in memory. So anywhere we have a value of a reference type— in a variable, as the value returned by a method, or the result of evaluating an expression—it’s possible for that value to be null.
However we get it, since the null reference doesn’t point to any actual object data we can’t use it to get at instance variable because there’s nothing to get. If we try to use the dot operator on an expression whose value is null, then we get a NullPointerException, which will crash our program. (It should really be called a NullReferenceException; “pointer” is old fashioned name for what Java calls a reference.)

Note 8.2.4.

Java actually provides a way to prevent errors like NullPointerException and others we’ve seen such as IndexOutOfBoundsException from crashing our whole program. But it is sadly beyond the scope of the AP curriculum. If you want to know more you can read the lesson ”Exceptions” from Oracle’s Java™ Tutorials series.
The good news about getting a NullPointerException is they’re usually pretty easy to debug. When the program crashes, we’ll get an error message pinpointing the specific line where the the exception occurred. From there we just need to check any expression on that line to the left of a dot. One of them must have been null. Then we just have to track back to where that value came from to figure out why it’s null at that point in the program. Did we forget to initialize a variable? Did some other code pass a null reference as an argument to the method?
As we’ll see in more detail in Section 8.3 Constructors, instance variables that are declared without an initial value are themselves initialized to null so one common source of null references is forgetting to initialize an instance variable which can lead to a NullPointerException if we try to access an instance variable from (or invoke an instance method on) that variable. And as we saw in Section 6.1 Creating and using arrays if we make an array with an array creation expression like new String[10] while the resulting array has places to store ten String references, they all start out null so when we make arrays with elements of a reference type we need to be sure to initialize the elements before we try to use them.

Subsection 8.2.3 Making instance variables private

Unlike method parameters and local variables declared inside the body of a method, which disappear as soon as the method returns, instance variables last as long as the object that contains them. And since we can pass object references as arguments to methods, including methods in other classes, that raises the question of what code is allowed to access these instance variables. Should any code that gets a reference to an object be able to access its instance variables, getting and setting their values?
In Java, the answer is that it’s up to the author of the class. The keyword private placed before the type in the variable declarations in Person is called an access modifier and it tells Java that those variables cannot be accessed by code outside the Person class, even if that code has a reference to a Person object.
Instance variables should almost always be declared private. The main reason is it makes it much easier to understand our own code: if we marked the variables as public and were trying to understand why a Person object’s age had changed we’d have to check every line of code in our whole program to see what code might have a reference to a Person object and might have assigned a new value to its age variable. Whereas with a private age variable, we know that the only code that could possibly have changed it has to be somewhere in the body of the Person class.
Making variables private also makes it easier to change our code later. If only code in the class can access a variable, then we can rename it, change its type, or even delete it, if we decide we want to store the information in a different way or don’t need it any more. But if it’s public we again have to look at all the code in any class that might use Person to see if it references that variable. Making variables is Java’s mechanism for data encapsulation or data hiding. In Section 8.4 Instance methods we’ll look at a common pattern for using public methods to give controlled access to private instance variables.

Activity 8.2.2.

Activity 8.2.3.

The following Person class keeps track of the name, email, and phone number of a person. What other data could you keep track of about a Person? Add another private instance variable of your choice. Do not worry about changing the constructor or other methods yet.
You have attempted of activities on this page.