Free for students · Ad-free · WCAG 2.1 AA Compliant · Accessibility

Class Variables and Methods

Lesson ~10 min read 8 MCQs

In simple terms: In simple terms, class variables and methods are shared by all objects of a class, like a team's total score, while instance variables and methods belong to each individual object, like a player's jersey number.

Why this matters

Imagine your school's robotics club, the "Circuit Breakers," is having a bake sale to raise money for a competition in Dallas. Each club member—Maya, Carlos, and Priya—is selling brownies.

Each person needs to track their own sales. Maya has sold $50 worth, Carlos has sold $35, and Priya has sold $60. That's individual data. But what about the team's total fundraising goal? Or the total number of brownies sold by everyone? That's shared data. It belongs to the whole club, not just one person.

In Java, we need a way to represent both types of information: the data that belongs to each individual object (like Maya's sales) and the data that's shared across all objects of that class (like the club's total). This lesson is all about that second type: the shared, team-level data and actions, using a special keyword called static.

Instance data belongs to individual objects, while class data is shared by all.

Concept overview

classDiagram
    class Student {
        <<Class>>
        +static int studentCount
        +static int getStudentCount()
    }
    class studentA {
        <<Object>>
        name: "Aaliyah"
        studentID: 101
    }
    class studentB {
        <<Object>>
        name: "Marcus"
        studentID: 102
    }
    class studentC {
        <<Object>>
        name: "Priya"
        studentID: 103
    }
    Student -- studentA : has instance
    Student -- studentB : has instance
    Student -- studentC : has instance
This diagram shows the relationship between a `Student` class and three `Student` objects. The `Student` class contains a static variable `studentCount` and a static method `getStudentCount()`, indicating these are shared. The objects, `studentA`, `studentB`, and `studentC`, each have their own individual instance data for `name` and `studentID`.

Core explanation

So far in our journey, we've focused on objects having their own unique state. If we have a Dog class, and we create two Dog objects, fido and spot, each has its own name and age. Changing Fido's age doesn't affect Spot's. These are called instance variables.

But what if we need information that belongs to the entire class? This is where class variables and class methods come in.

The static Keyword: The Class's Shared Property

To tell Java that a variable or method belongs to the class itself and not to individual objects, we use the static keyword.

Think of it like this: Imagine a Student class for your high school.

  • Instance Variables
    studentID, gpa, name. Each student object has its own unique values for these. My GPA is mine, yours is yours.
  • Class Variable
    studentCount. We might want to track how many total students have been enrolled. This number doesn't belong to any single student; it belongs to the Student class as a whole.

When we declare a variable static, every object of that class shares a single copy of that variable.

The `Student` class showing instance variables for each object and a shared static class variable.
public class Student {
    // Instance variables - each Student object gets its own copy
    private String name;
    private int studentID;

    // Class variable - all Student objects share ONE copy of this
    public static int studentCount = 0;

    public Student(String name, int id) {
        this.name = name;
        this.studentID = id;
        studentCount++; // Increment the SHARED counter
    }
}

Every time the Student constructor runs (i.e., a new Student object is created), it increments the same studentCount variable. If we create three Student objects, studentCount will be 3.

Accessing Static Members

Since static variables belong to the class, not an object, the proper way to access them is by using the class name itself, followed by the dot operator.

// Creating some students
Student studentA = new Student("Aaliyah", 101);
Student studentB = new Student("Marcus", 102);

// Accessing the static variable using the CLASS NAME
System.out.println("Total students: " + Student.studentCount); // Prints "Total students: 2"
Always access static members using the class name, not an object reference.

Static Methods: Actions for the Class

Just like variables, methods can also be static. These are utility methods that perform an action for the class, not on behalf of a specific object.

The most famous example is the Math class in Java. You never write Math myMath = new Math();. Instead, you just call the methods directly on the class:

  • Math.random()
  • Math.pow(2, 3)
  • Math.sqrt(64)

These are all static methods. They perform a calculation but don't need any information from a specific Math object to do their job.

Let's add a static method to our Student class:

public class Student {
    // ... (previous variables and constructor)

    // A static method to get the shared student count
    public static int getStudentCount() {
        return studentCount;
    }
}

We would call this using Student.getStudentCount().

The Big Rule for Static Methods

Here is the most important rule to remember, and a common source of AP exam questions:

A static method cannot access instance variables or call instance methods directly.

Why? Think about our analogy. A static method is like the principal making a school-wide announcement from the main office. The principal (static method) knows about the shared announcement board (static variable studentCount).

But can the principal, from the office, know what's in your specific locker (instance variable)? No. They don't have a specific student object to work with. The static context exists independently of any object.

Look at this code, which will not compile:

public class Student {
    private String name; // Instance variable

    public static String getAName() {
        return name; // COMPILE ERROR!
        // Which student's name? Aaliyah's? Marcus's?
        // The static method doesn't know, because it's not tied to an object.
    }
}

The error message you'd see is: "non-static variable name cannot be referenced from a static context." When you see this error, it's a huge clue that you're mixing up class-level and object-level access.

However, a static method can access an instance variable if it's given an object as a parameter.

public static void printStudentInfo(Student s) {
    // This is okay! We were given a specific student object 's'.
    System.out.println(s.name);
}

The final Keyword: Making Constants

One last piece of the puzzle is the final keyword. When you declare a variable final, its value can be assigned only once. It becomes a constant.

This is often combined with public static to create globally accessible constants.

For example, a Calculator class might have a constant for Pi. It's public so everyone can see it, static because it belongs to the class (there's only one value of Pi), and final because Pi doesn't change.

public class MathConstants {
    public static final double PI = 3.14159;
    public static final double E = 2.71828;
}

By convention, public static final variable names are written in all uppercase letters with underscores. This makes them easy to spot in code.

You can then use this constant from anywhere in your program: double circleArea = MathConstants.PI * radius * radius;

And if you try to change it, you'll get a compiler error: MathConstants.PI = 4.0; // COMPILE ERROR! Cannot assign a value to a final variable.

This combination of static and final is incredibly useful for creating clear, reliable, and maintainable code.

Tracing how `studentCount` increments with each new `Student` object.

See it in action

python
Line 1
Output
Click Run to see the output.

        
Try these
    © Shrutam.ai

    Worked examples

    Let's walk through a couple of examples to make these concepts solid.

    Example 1

    Tracking Video Game High Scores

    Problem: You're building a simple arcade game. Each Game instance represents one playthrough with its own score. You also need to track the single highest score achieved across all games ever played.

    Solution Walkthrough:

    1. 1
      Identify Instance vs. Class Data
      • The score of a single game belongs to that specific game object. This should be an instance variable.
      • The highScore is shared across all games. If a new game beats the old high score, this single value needs to be updated for everyone. This should be a class variable (static).
    2. 2

      Create the Game Class:

      public class Game {
          // Instance variable for this specific game's score
          private int score;
      
          // Class variable for the best score across ALL games
          private static int highScore = 0;
      
          // Constructor for a new game
          public Game(int finalScore) {
              this.score = finalScore;
              // After a game is finished, check if it set a new high score
              if (this.score > highScore) {
                  highScore = this.score; // Update the SHARED high score
              }
          }
      
          // Getter for this game's score (instance method)
          public int getScore() {
              return this.score;
          }
      
          // Getter for the all-time high score (class method)
          public static int getHighScore() {
              return highScore;
          }
      }
    3. 3
      Explain the "Why"
      • We made highScore static because there is only one "all-time high score" for the entire system. It doesn't belong to game1 or game2; it belongs to the Game concept itself.
      • Inside the constructor, we update highScore if the current game's score is greater. Notice we can access the static variable highScore directly from an instance context (the constructor).
      • The getHighScore() method is static because you should be able to ask "What's the high score?" without needing to have a specific game object in your hand. You call it using Game.getHighScore().
    4. 4
      Common Wrong Turn
      A common mistake is to make highScore an instance variable. If you did that, each Game object would have its own separate highScore. game1 would think the high score is X, and game2 would think it's Y. They wouldn't be sharing information, defeating the whole purpose.

    Example 2: A Simple UnitConverter

    Problem: Create a utility class that converts inches to centimeters. You should not need to create an object of this class to use it.

    Solution Walkthrough:

    1. 1
      Identify the Need
      This is a pure utility. We don't need to store any state in an object. We just need a function that takes a number and returns another number. This is a perfect use case for a static method. We also need the conversion factor, which is a constant.
    2. 2

      Create the UnitConverter Class:

      public class UnitConverter {
          // A constant for the conversion factor.
          // It's final because it never changes.
          // It's static because it belongs to the class, not an object.
          public static final double INCHES_TO_CM = 2.54;
      
          // A static method to perform the conversion.
          // It takes the value to convert as a parameter.
          public static double inchesToCm(double inches) {
              return inches * INCHES_TO_CM;
          }
      }
    3. 3
      Using the Class
      public class Main {
          public static void main(String[] args) {
              double heightInInches = 70.0;
              // Call the static method directly on the class
              double heightInCm = UnitConverter.inchesToCm(heightInInches);
              System.out.println("A height of " + heightInInches + " inches is " + heightInCm + " cm.");
              // We can also access the public static final constant
              System.out.println("The conversion factor is: " + UnitConverter.INCHES_TO_CM);
          }
      }
    4. 4
      Explain the "Why"
      • We made the method static because the conversion logic isn't tied to a specific object's state. It's a general-purpose function.
      • We made the conversion factor public static final because it's a universal constant that other parts of our program might want to reference directly. It's safe to make it public because final prevents it from being changed.
      • This design prevents users from creating useless objects, like UnitConverter converter = new UnitConverter();. The functionality is all at the class level.
    Tracing `highScore` updates as new `Game` objects are created.
    The critical difference between instance and static variables for shared data.

    Try it yourself

    Time to put your skills to the test.

    Problem 1: The Book Club

    Create a Book class. Each Book object should have an instance variable for its title (a String). The class should also keep track of the total number of Book objects that have been created.

    • Create a public static integer variable to count the books.
    • In the Book constructor, be sure to increment this counter.
    • Create a public static method called getBookCount() that returns the total count.

    Problem 2: The Config Class

    Your application needs a central place to store configuration settings. Create a Config class that holds the application's version number and name. These values should be constants that are accessible throughout your entire program but cannot be changed.

    • Create a public static final String for the APP_NAME, initialized to "Shrutam Study App".
    • Create a public static final double for the APP_VERSION, initialized to 1.0.