Class Variables and Methods
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.
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
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 theStudentclass as a whole.
When we declare a variable static, every object of that class shares a single copy of that 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"
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.
See it in action
Worked examples
Let's walk through a couple of examples to make these concepts solid.
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:
- 1Identify Instance vs. Class Data
- The
scoreof a single game belongs to that specific game object. This should be an instance variable. - The
highScoreis 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).
- The
- 2
Create the
GameClass: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; } } - 3Explain the "Why"
- We made
highScorestaticbecause there is only one "all-time high score" for the entire system. It doesn't belong togame1orgame2; it belongs to theGameconcept itself. - Inside the constructor, we update
highScoreif the current game'sscoreis greater. Notice we can access thestaticvariablehighScoredirectly from an instance context (the constructor). - The
getHighScore()method isstaticbecause 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 usingGame.getHighScore().
- We made
- 4Common Wrong TurnA common mistake is to make
highScorean instance variable. If you did that, eachGameobject would have its own separatehighScore.game1would think the high score is X, andgame2would 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:
- 1Identify the NeedThis 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
staticmethod. We also need the conversion factor, which is a constant. - 2
Create the
UnitConverterClass: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; } } - 3Using 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); } } - 4Explain the "Why"
- We made the method
staticbecause 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 finalbecause it's a universal constant that other parts of our program might want to reference directly. It's safe to make itpublicbecausefinalprevents 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.
- We made the method
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 staticinteger variable to count the books. - In the
Bookconstructor, be sure to increment this counter. - Create a
public staticmethod calledgetBookCount()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 Stringfor theAPP_NAME, initialized to "Shrutam Study App". - Create a
public static final doublefor theAPP_VERSION, initialized to1.0.
Practice — 8 questions
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.
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
}
}
- 3.7.A: Develop code to define behaviors of a class through class methods.
- 3.7.B: Develop code to declare the class variables that belong to the class.
- 3.7.A.1
- Class methods cannot access or change the values of instance variables or call instance methods without being passed an instance of the class via a parameter.
- 3.7.A.2
- Class methods can access or change the values of class variables and can call other class methods.
- 3.7.B.1
- Class variables belong to the class, with all objects of a class sharing a single copy of the class variable. Class variables are designated with the static keyword before the variable type.
- 3.7.B.2
- Class variables that are designated public are accessed outside of the class by using the class name and the dot operator, since they are associated with a class, not objects of a class.
- 3.7.B.3
- When a variable is declared final, its value cannot be modified.
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
Read what Saavi narrates
Hello, and welcome to Shrutam! I'm Saavi, and today we're going to talk about a really important concept in Java: the difference between things that belong to an individual, and things that belong to a team.
Imagine your school's robotics club is having a bake sale. Each person—Maya, Carlos, and Priya—is tracking their own individual sales. That's their personal data. But what about the team's total fundraising goal? Or the total number of brownies sold by everyone combined? That's shared information. It belongs to the whole club, not just one person.
In Java, we call this shared information `static`. We use the `static` keyword for variables and methods that belong to the class as a whole, not to any single object. Think of it like a main announcement board at your school. Each student has their own locker with their own stuff... those are instance variables. But the announcement board is shared by everyone. That's a static variable.
Let's look at an example. Imagine a simple video game. Each time you play, you get a score. That score belongs to that specific game. But we also want to track the single highest score achieved across ALL games ever played.
We would create a `Game` class. Inside it, we'd have a regular variable for the score. But we'd also have a `static` variable called `highScore`. Because it's static, there's only one copy of it, shared by all game objects. When you finish a game, the code checks if your score is higher than the current `highScore`. If it is, it updates that single, shared value. Now, the next time anyone plays, they're competing against that new, updated high score.
Here's the most common mistake students make: they try to access a personal, instance variable from a static, shared context. It's like trying to find out what's in a specific student's locker from the principal's office without knowing which student you're talking about. It doesn't work! A static method can't see instance variables unless you give it a specific object to look at.
Remembering the difference between shared `static` members and individual instance members will make your code much more organized and powerful. You've got this!
A `static` method isn't connected to any specific object, so it doesn't know *which* object's instance variable to use. This causes the famous "non-static variable...cannot be referenced from a static context" compiler error.
If a `static` method needs to use instance data, you must pass the object to it as a parameter.
If you omit `static`, the variable becomes an instance variable. Every object will get its own separate copy, and they won't share changes.
When you need a single variable shared by all objects of a class (like a counter or a high score), always declare it with `static`.
While this might compile, it's very misleading. It makes it look like the variable belongs to `myObject`, but it actually belongs to the class. Another programmer (or you, six months later) will get confused.
Always access `static` members using the class name: `ClassName.staticVariable`.
The `final` keyword explicitly forbids this. It makes the variable a constant.
If you need a variable whose value can change, do not declare it as `final`. Use `final` only for true constants.
It's not a syntax error, but it's pointless. The whole point of a `static` utility class is that you don't need to create objects from it.
To signal that a class should not be instantiated, you can provide a `private` constructor: `private UnitConverter() {}`. This prevents anyone from creating an object of that class.