In Java, the terms instance and object mean (very close to) the same thing. See the Primitive types vs references exercises for practice constructing and using instances (objects).

Static is the opposite of instance. Variables and methods can be declared as static. A method that is declared without the static modifier is an instance method. A variable declared outside a method without the static modifier is an instance variable.

Parameters are declared within a method header. Parameters are neither static nor instance. Local variables are declared within a method. Local variables are neither static nor instance.

Static vs instance in client code

Static methods & fields

System.out.println(Math.pow(2, 8));  // prints 256.0
System.out.println(Math.sqrt(4.0));  // prints 2.0
System.out.println(Math.PI);         // prints 3.141592653589793

The Math class contains static methods, including pow and sqrt. A static method runs directly on a class, not on a specific instance (object) of a class.

Methods that do not require access to state (values of instance variables) are often declared as static.

The Math class also contains public static final fields, including PI. The static and final modifiers are often confused. The final modifier prevents the value of a field from being changed after it has been set. The static modifier attaches the field to the class rather than to an instance (object) of the class.

Instance methods

String firstName = "Brandon";
String lastName = "Horn";

System.out.println(firstName.indexOf("o"));  // prints 5 
System.out.println(lastName.indexOf("o"));   // prints 1

System.out.println(String.indexOf("o"));     // compile time error

indexOf is an instance method of the String class. It runs on a specific instance (object) of type String.

Methods that require access to state must not be declared as static.

The first and second calls to indexOf("o") return different results because they are run on different instances (objects). The String object "Brandon" contains "o" at index 5. The String object "Horn" contains "o" at index 1.

The third call to indexOf("o") causes a compile time error. indexOf is an instance method, not a static method. It must be run on a specific instance (object) of type String, not directly on the String class.

Static vs instance inside a class

Instance variables exist inside a specific instance (object) of a class. Each object (instance) of a class gets its own copies of that class’s instance variables.

Instance methods run on a specific instance (object) of a class. The Primitive types vs references exercises demonstrate the use of instance variables by instance methods.

Static variables exist as part of a class. Exactly one copy of each static variable exists regardless of whether zero, one, or more objects of that class have been created.

Correct example with Student class

public class Student
{
    private static String schoolCode;
    
    private int studentNumber;
    
    public Student(int stuNum)
    {
        studentNumber = stuNum;
    }
    
    public int getStudentNumber()
    {
        return studentNumber;
    }
    
    public String getStudentID()
    {
        return schoolCode + "-" + studentNumber;
    }
    
    public static String getSchoolCode()
    {
        return schoolCode;
    }
    
    public static void setSchoolCode(String schCode)
    {
        schoolCode = schCode;
    }
}

public class StudentRunner
{
    public static void main(String[] args)
    {
        Student.setSchoolCode("MHHS");
        
        Student s1 = new Student(567);
        Student s2 = new Student(678);
        
        System.out.println(s1.getStudentID());
        System.out.println(s2.getStudentID());
        
        System.out.println(Student.getSchoolCode());
    }
}

School.schoolCode points to “MHHS”. s1 points to a box containing studentNumber, which stores 567. s2 points to a different box containing a different copy of studentNumber, which stores 678.

The diagram above shows the memory state after the first 3 lines of the main method (and throughout the rest of the method).

All students share the same school ID, which is stored in the static variable schoolCode. Each student has a unique student number, which is stored in the instance variable studentNumber.

A student ID is created by concatenating the school code, a dash (-), and the student number. In the example above, s1.getStudentID() returns "MHHS-567" and s2.getStudentID() returns "MHHS-678".

getStudentID is (and must be) an instance method of Student. getStudentID accesses the static variable schoolCode and the instance variable studentNumber. Instance methods can access both static and instance variables.

The code in the main method prints:

MHHS-567
MHHS-678
MHHS

Incorrect example with static getStudentID method

public class Student
{
    // static modifier added to getStudentID
    public static String getStudentID()
    {
        return schoolCode + "-" + studentNumber;
    }
    
    // All other code in Student remains unchanged.
}

Consider the above modification to the Student class.

The getStudentID method has been incorrectly declared as static. Static methods cannot access instance variables. The attempt to access the instance variable studentNumber results in a compile time error.

A static method is run on a class, not on a specific instance (object) of a class. Since there is no instance, there are no instance variables to access.

In this (incorrect) example, the method would be called as:

System.out.println(Student.getStudentID());

This is equivalent to asking for the student ID of the Student class, rather than of a specific student. The request doesn’t make sense.

Incorrect example with static studentNumber field

public class Student
{
    // static modifier added to studentNumber
    private static int studentNumber;
    
    // All other code in Student remains unchanged.
}

Consider the above modification to the Student class.

The studentNumber field has been incorrectly declared as static. Static fields exist once per class, not once per instance of a class.

The original StudentRunner main method has been copied below.

public static void main(String[] args)
{
    Student.setSchoolCode("MHHS");
    
    Student s1 = new Student(567);
    Student s2 = new Student(678);
    
    System.out.println(s1.getStudentID());
    System.out.println(s2.getStudentID());
    
    System.out.println(Student.getSchoolCode());
}

School.schoolCode points to “MHHS”. School.studentNumber stores 678. s1 points to an empty box. s2 points to a different empty box.

The diagram above shows the memory state after construction of the second Student object (with the studentNumber field incorrectly declared as static). As a static variable, studentNumber exists once, not once per object.

The code in the main method prints:

MHHS-678
MHHS-678
MHHS

Incorrect example that appears correct

public static void main(String[] args)
{
    Student.setSchoolCode("MHHS");
    
    Student s1 = new Student(567);
    System.out.println(s1.getStudentID()); // moved here

    Student s2 = new Student(678);
    System.out.println(s2.getStudentID());
    
    System.out.println(Student.getSchoolCode());
}

The code above is a modified version of the StudentRunner main method. The code to print s1.getStudentID() has been moved immediately after the construction of the first Student object.

Even with the Student variable studentNumber incorrectly declared as static, the code above correctly prints:

MHHS-567
MHHS-678
MHHS

Each time the Student constructor runs, it sets the value of the static variable studentNumber. The value of the variable is correct each time getStudentID() is run. This does not mean the Student class is correct.

If the line:
System.out.println(s1.getStudentID());

is added to the end of the main method, it will incorrectly print:
MHHS-678

Help & comments

Get help from AP CS Tutor Brandon Horn

Comment on Static vs instance