Types of Variables
In Java, variables are categorized into three types based on where they are declared. Understanding their scope (where they can be accessed) and lifetime (how long they exist) is crucial.
| Type | Declaration | Scope | Lifetime |
|---|---|---|---|
| Instance | Inside a class, but outside any method. | Throughout the class (except static methods). | As long as the object exists in memory. |
| Local | Inside a method or a block of code {}. |
Only within that method/block. | Only until the method/block finishes executing. |
| Class (Static) | Inside a class with the static keyword. |
Throughout the class. | For the entire duration of the program's execution. |
There are a total of three types of variables that you can declare in your program:
- Instance: Unique to each object.
- Static: Shared by all objects of the class.
- Local: Exist only within a specific block of code.
- Instance Variables: These belong to a specific instance (object), and every instance has its own copy of the variable. You already worked with these in earlier lessons.
- Local Variables: These belong to a specific code block, such as methods, constructors, and
iforwhileblocks. You have already used these in your programs. - Static Variables: These belong to the class as a whole rather than any specific instance. There is only one copy of a static variable in memory, which is shared by all instances. Use caution when declaring a variable as static, as any change made by one instance affects all others.
When you declare a variable static in a class, then you only have one copy of that variable in memory for any number of objects that might be created with that class. This is in contrast to the instance variables, in which, there is an individual copy of that variable for every single object that was created.
Task: Using static variables to track state across all instances.
class Student {
static int numberOfStudents;
private String name;
public String getFirstName() {
return this.name;
}
public void setFirstName(String name) {
this.name= name;
}
public int getNumberOfStudents() {
return numberOfStudents;
}
public Student() {
numberOfStudents++;
}
public static void main(String[] args) {
Student student1 = new Student();
student1.setFirstName("John");
System.out.println(student1.getNumberOfStudents());
Student student2 = new Student();
student2.setFirstName("Jane");
System.out.println(student2.getNumberOfStudents());
}
}
In the above example, the variable name is an instance variable because it does not have the static modifier. However, the variable numberOfStudents is a static variable. It makes sense to make name an instance variable, as every object (instance) must store its own value to distinguish between individual students.
In this example, you also see a no-argument constructor for the Student class which increments the value of numberOfStudents. Whenever a Student object is instantiated with the new keyword, the value of the static variable numberOfStudents is increased by 1.
While every instance should keep a separate value for name, you do not need a separate copy for every instance when tracking the total number of students. You only need one value across all instances. In scenarios like this, you declare a static variable. A static variable is also called a class variable because it belongs to the class itself, although every instance can access it.
Another Example
Now let us take another look at the difference between instance and static variables. The picture below depicts code in which two instances of Customer are created, and the name of each Customer object is initialized. This class also has a static variable customerCount. Notice that you have two separate copies of the name variable (one for each object instantiated), but you only have one copy of the static variable, which belongs to the class.
Both object instances can access the static variable and make changes to its value. Even though instances can access a static variable through an instance identifier, it is recommended to use the class name instead. In this example, while we might access the static variable using an instance to illustrate the concept, the best practice is to access it through the class name. Therefore, both customer1.customerCount++ and customer2.customerCount++ should be replaced with Customer.customerCount++.
- Since static variables are stored in a single memory location, any instance can overwrite the static value set by another instance.
- Although you can reference a static variable through an instance, creating an instance is not required; static variables should be accessed through the class name.
For a deeper dive into how static variables and methods allow you to manage state across an entire class, check out Unit 3.7: Class Variables and Methods.
Variable Scope
Scope refers to the region of a program where a variable is accessible. In Java, a variable's scope is strictly defined by where it is declared.
- Variables exist only within the block of code where they are defined. For local variables, this is from their declaration to the end of the surrounding curly brace
}.
Understanding scope is critical for avoiding bugs and ensuring that data is only manipulated where intended.
Local Variable Scope
A local variable can only be accessed by statements that appear after its declaration and within the same code block.
Task: Identifying the scope of local variables.
class Lion {
static int totalLions;
private int age;
public void speak() {
String greet = null;
if (age < 10) {
int i = 0;
System.out.println(i);
greet = "Roar...";
} else {
greet = "Whine...";
}
System.out.println(greet);
}
public Lion(int age) {
totalLions++;
this.age = age;
}
}
The local variable greet in the speak method cannot be accessed by the constructor.
Static and Instance Variable Scope
Static and instance variables can be accessed by any code block within the class, and even outside the class if they are not declared as private. While these variables can be declared anywhere in the class, it is best practice to declare all fields at the top, just below the class declaration.
- For a more advanced discussion on how scope rules function within class methods and constructors—including how to handle variable "shadowing"—see the dedicated section on Unit 3.8: Scope and Access.
- To learn how to use the
thiskeyword to distinguish between instance variables and local parameters, see Unit 3.9: The this Keyword.