AP Computer Science A • Class Creation

Class Variables and Methods

Understanding how the static keyword enables shared state and behavior across all instances of a class.

AP Computer Science A illustration with code, binary digits, and programming braces
Inside this lesson 9 sections 5 questions 8 figures

SECTION 1

Historical Context & Motivation

The distinction between class-level and instance-level members has roots that trace back to the earliest object-oriented programming languages. As software systems grew in complexity, developers needed a mechanism to share data and behavior among all objects of the same type without duplicating that information in every single instance. The static keyword in Java directly descends from design decisions made across decades of language evolution, formalizing the idea that some properties belong to the class blueprint itself rather than to any particular object created from it.

1967 • Simula 67 Introduces Classes

Ole-Johan Dahl and Kristen Nygaard create Simula, the first language with classes and objects, establishing the blueprint-instance relationship that would underpin all OOP.

1980 • Smalltalk-80 Formalizes Class Methods

Smalltalk distinguishes between messages sent to instances and messages sent to the class itself, solidifying the concept of class-side behavior.

1983 • C++ Adopts static Keyword

Bjarne Stroustrup borrows the static keyword from C and repurposes it to denote class-level members shared across all instances.

1995 • Java Standardizes static

James Gosling's Java language inherits the static keyword from C++, making it the standard way to declare class variables and class methods on the AP exam's language of choice.

The central question this concept addresses is deceptively simple: if every BankAccount object tracks its own balance, where should the interest rate live when it is identical for every account? Storing a separate copy in each object wastes memory and creates a maintenance nightmare if the rate changes. Class variables and methods solve this problem by anchoring shared data and utility behavior to the class itself rather than to any one object.

SECTION 2

Core Principles & Definitions

In Java, every field or method declared with the static modifier belongs to the class rather than to any instance. These members are loaded into memory once when the class is first referenced by the JVM and persist for the lifetime of the program. Understanding the four core principles below is essential for both the AP exam and for writing well-structured Java code.

1

Class (Static) Variables

Declared with static, a class variable has exactly one copy shared by all instances. Changes made through any reference are visible everywhere. Example: a counter tracking the total number of objects created.
2

Instance Variables

Declared without static, an instance variable has a separate copy in every object. Each object's state is independent. Example: the balance of an individual bank account.
3

Class (Static) Methods

Invoked on the class name (e.g., Math.sqrt()). They cannot access instance variables or this because no specific object is guaranteed to exist when they run.
4

Access Rules

Static methods can only access static members directly. Instance methods can access both static and instance members. Violating this rule is one of the most common compile-time errors on the AP exam.

SECTION 3

Visual Explanation

Class vs. Instance Members in MemoryStudent Class (Static Area)static int totalStudents = 3static int getTotal() { ... }Instance: s1name = "Alice"gpa = 3.8getName(), setGpa()Instance: s2name = "Bob"gpa = 3.5getName(), setGpa()Instance: s3name = "Carol"gpa = 3.9getName(), setGpa()Dashed arrows show all instances sharing the single static variable.Each instance has its own copy of name and gpa (instance variables).Instance dataStatic (shared) data
The violet box at the top represents the single static area in memory where totalStudents resides. Each colored box below is a separate object on the heap with its own name and gpa. The dashed arrows emphasize that every instance references the same shared counter.

Notice how the static variable totalStudents exists in a single location associated with the Student class itself. When any constructor increments this counter, the change is visible through every reference — s1.totalStudents, s2.totalStudents, or (preferably) Student.totalStudents all evaluate to the same value. The AP exam strongly expects you to call static members using the class name rather than an object reference to convey intent clearly.

One ticket agent hands a new stub to a patron while another patron retains an issued stub.Each issued ticket keeps its own number while one class counter advances. Shared class state and separate instance state serve different purposes.

Two ticket instances retain IDs 1 and 2 while one static nextNumber advances to 3.The Ticket constructor copies nextNumber into the new instance and then increments the shared counter. Tickets keep IDs 1 and 2 while nextNumber becomes 3. This counter records constructions.

SECTION 4

How Static Members Work Under the Hood

When the JVM loads a class for the first time, it allocates space for all static fields in a region of memory called the method area (metaspace). This happens before any constructor runs and before any object of that class exists. Static variables are initialized in the order they appear in the source code, and they remain alive until the class is unloaded — effectively for the entire program. Instance fields, by contrast, are allocated on the heap each time new is invoked.

Declaration Syntax

STATIC VARIABLE

privatestaticintcount=0;private static int count = 0;

The static keyword appears between the access modifier and the type. This variable is shared by all instances.

STATIC METHOD

publicstaticintgetCount()returncount;public static int getCount() { return count; }

A static method can only directly reference static fields. It cannot use this or call instance methods without an explicit object reference.

STATIC FINAL CONSTANT

publicstaticfinaldoubleTAXRATE=0.07;public static final double TAX_RATE = 0.07;

Combining static with final creates a class-level constant. By convention these use ALL_CAPS naming. The value cannot be reassigned after initialization.

ℹ
AP Exam Pitfall

SECTION 5

Static vs. Instance — Detailed Breakdown

Access Rules: Who Can See What?Static Methodpublic static void doWork()✓ Can access static variables✓ Can call other static methods✗ Cannot access instance variables✗ Cannot use 'this'Instance Methodpublic void doWork()✓ Can access static variables✓ Can access instance variables✓ Can call static methods✓ Can use 'this'Calling ConventionClassName.methodName()objectRef.methodName()Instance methods have strictly more access than static methods.
The left panel shows what static methods can and cannot do; the right panel shows that instance methods enjoy full access. The asymmetry is the single most tested detail on the AP exam.
FeatureStatic (Class) MemberInstance Member
Keywordstatic(none — default)
Copies in memoryExactly one per classOne per object
Accessed viaClassName.memberobjectRef.member
LifetimeClass loading → program endObject creation → garbage collection
Can use this?NoYes
Typical use caseCounters, constants, utility methodsObject state and behavior

Comprehensive comparison of static vs. instance members

SECTION 6

Worked Example — Designing a Dog Class

The following example demonstrates a complete class that uses both static and instance members. We will trace through the code step by step to see how the static variable dogCount changes as new objects are created.

Worked example

  1. 1

    Step 1 — Define the Class

    We declare a Dog class with one static variable, one static method, and standard instance members: public class Dog { private static int dogCount = 0; private String name; public Dog(String name) { this.name = name; dogCount++; } public static int getDogCount() { return dogCount; } public String getName() { return name; } }
    Before any objects are created, dogCount is initialized to 0.
  2. 2

    Step 2 — Create the First Object

    Dog d1 = new Dog("Rex"); The constructor sets this.name to "Rex" and increments dogCount.
    dogCount is now 1. d1.getName() returns "Rex".
  3. 3

    Step 3 — Create the Second Object

    Dog d2 = new Dog("Bella"); The same constructor runs again, setting the new object's name to "Bella" and incrementing the same static dogCount.
    dogCount is now 2. Both Dog.getDogCount() and d1.getDogCount() return 2.
  4. 4

    Step 4 — Verify Independence of Instance State

    System.out.println(d1.getName()); // Rex System.out.println(d2.getName()); // Bella System.out.println(Dog.getDogCount()); // 2 Each object retains its own name, but both share dogCount. This is the fundamental static-vs-instance distinction in action.
    Instance variables are independent; the static variable is shared and consistent across all objects.

SECTION 7

Strengths, Limitations & Common Mistakes

StrengthsLimitations
Memory efficient — one copy shared by all instances avoids redundant storageOveruse couples code tightly, making testing and subclassing harder
Accessible without creating objects, ideal for utility methods like Math.max()Static methods cannot be overridden polymorphically; they are hidden, not overridden
Constants declared static final provide a single source of truth for values like π or tax ratesMutable static variables create hidden global state, which can introduce concurrency bugs in multithreaded programs
Enables clean factory method patterns and counting utilitiesCannot access instance state directly — requires an object reference to reach non-static fields

When to use and when to avoid static members

★

Key takeaway

DESIGN GUIDELINE

SECTION 8

Connection to Advanced Concepts

While the AP exam focuses on basic static usage, the concept opens the door to several advanced patterns in software engineering. Understanding how Java's static keyword relates to these patterns provides useful context, even if the advanced topics themselves are beyond the AP scope.

AP-Level ConceptAdvanced Extension
Static variable as object counterSingleton Pattern — uses a private static reference to guarantee exactly one instance of a class exists
Static utility methods (e.g., Math.abs())Static Factory Methods — named static methods like List.of() that replace constructors for flexible object creation
static final constantsEnum Types — a type-safe alternative to groups of static constants, e.g., enum Season { WINTER, SPRING, ... }
Static methods cannot be overriddenMethod Hiding vs. Overriding — in inheritance, a static method in a subclass hides (not overrides) the parent's version, affecting polymorphic dispatch

How AP-level static concepts extend into advanced Java

If you continue into college-level courses such as Data Structures or Software Engineering, you will encounter design debates about global mutable state — the risks that come with non-final static variables. Modern best practice favors dependency injection over static access for anything beyond constants and pure utility functions, because injected dependencies are easier to mock in unit tests and reason about in concurrent systems.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Consider the following class: public class Widget { private static int count = 0; private int id; public Widget() { count++; id = count; } public static int getCount() { return count; } public int getId() { return id; } } After executing the following code, what does Widget.getCount() return? Widget w1 = new Widget(); Widget w2 = new Widget(); Widget w3 = new Widget();
  • A. 0
  • B. 1
  • C. 3
  • D. The code does not compile
Show answer (C)
The correct answer is C (3). Each call to the Widget constructor increments the single static variable count. After three objects are created, count equals 3. Option A (0) would be correct only if no constructors had run. Option B (1) confuses static with instance behavior — it would be true if each object had its own counter resetting to 0. Option D is wrong because the code is syntactically and semantically valid.

Question 2: BASIC CALCULATION

Given the following class: public class Account { private static double interestRate = 0.05; private double balance; public Account(double b) { balance = b; } public static void setRate(double r) { interestRate = r; } public double getProjected() { return balance * (1 + interestRate); } } What is the output of this code? Account a1 = new Account(1000); Account a2 = new Account(2000); Account.setRate(0.10); System.out.println(a1.getProjected()); System.out.println(a2.getProjected());
  • A. 1050.0 and 2100.0
  • B. 1100.0 and 2200.0
  • C. 1050.0 and 2200.0
  • D. 1100.0 and 2100.0
Show answer (B)
The correct answer is B (1100.0 and 2200.0). The static method setRate(0.10) changes the single shared interestRate to 0.10 before either getProjected() is called. So a1 computes 1000 × 1.10 = 1100.0 and a2 computes 2000 × 1.10 = 2200.0. Option A uses the original 0.05 rate, ignoring the update. Option C incorrectly applies the old rate to only a1. Option D incorrectly applies the old rate to only a2.

Question 3: INTERMEDIATE

Which of the following changes would cause a compile-time error in the Account class from Problem 2? // Option A: In setRate public static void setRate(double r) { interestRate = r; System.out.println(balance); // added line } // Option B: In getProjected public double getProjected() { return balance * (1 + interestRate); } // Option C: New static method public static double getRate() { return interestRate; } // Option D: In constructor public Account(double b) { balance = b; interestRate = 0.05; }
  • A. Adding System.out.println(balance); inside setRate
  • B. The existing getProjected method as written
  • C. Adding a new static method getRate() that returns interestRate
  • D. Assigning interestRate inside the constructor
Show answer (A)
The correct answer is A. The method setRate is static, so it cannot access the instance variable balance directly — this produces a compile-time error. Option B compiles fine because getProjected is an instance method and can access both instance and static fields. Option C compiles because a static method returning a static variable is perfectly valid. Option D compiles because a constructor is an instance context that can access static variables.

Question 4: APPLIED

Write a class called Ticket that meets the following requirements: • A static variable nextNumber that starts at 1 and auto-increments each time a new Ticket is created. • An instance variable ticketNumber that stores the number assigned to that specific ticket. • An instance variable holder of type String. • A constructor that takes the holder's name and assigns the next ticket number. • A static method getNextNumber() that returns the value of nextNumber. • A toString() method that returns a String in the format "Ticket #X: holderName".
Show answer
Sample solution: public class Ticket { private static int nextNumber = 1; private int ticketNumber; private String holder; public Ticket(String holder) { this.holder = holder; this.ticketNumber = nextNumber; nextNumber++; } public static int getNextNumber() { return nextNumber; } public String toString() { return "Ticket #" + ticketNumber + ": " + holder; } } Rubric: Point 1: private static int nextNumber = 1; — must be static and initialized to 1. Point 2: Instance variables ticketNumber and holder are declared as non-static with correct types and private access. Point 3: Constructor assigns ticketNumber = nextNumber before incrementing nextNumber++. Both operations must be present and in the correct order (assign then increment, or use post-increment). Point 4: getNextNumber() is declared static and returns nextNumber. Point 5: toString() returns the exact format "Ticket #" + ticketNumber + ": " + holder. Must use instance variables, not static.

Question 5: CRITICAL THINKING

A student proposes the following modification to the Dog class from Section 6: they add a static method called rename that takes a new name as a parameter and sets name = newName. (a) Explain why this method will not compile. (b) Provide two distinct ways to fix the method so that it successfully renames a specific Dog, and explain the trade-off of each approach. (c) State which fix is preferred from an OOP design perspective and justify your answer.
Show answer
(a) The method will not compile because name is an instance variable, and a static method has no implicit this reference. The compiler cannot determine which Dog's name to modify, so it rejects the access with a compile-time error. (b) Fix 1: Remove the static keyword, making rename an instance method: public void rename(String newName) { name = newName; }. Trade-off: requires an existing object reference to call (e.g., d1.rename("Max")). Fix 2: Keep it static but pass a Dog parameter: public static void rename(Dog d, String newName) { d.name = newName; }. Trade-off: this works only because static methods within the same class can access private fields of objects of that class, but the design is awkward — callers must pass an explicit object rather than calling the method naturally on the object. (c) Fix 1 is preferred because renaming is fundamentally an operation on a specific Dog instance, and OOP design dictates that behavior tied to an object's state should be an instance method. Fix 2 treats the method as a utility acting on external data, which undermines encapsulation and is not idiomatic Java. Rubric: Point 1 — Correctly identifies the compile-time error as static method accessing instance variable without this. Point 2 — Provides Fix 1 (remove static) with trade-off stated. Point 3 — Provides Fix 2 (add parameter) with trade-off stated and correctly identifies which approach is preferred with OOP justification.

Varsity Tutors • AP Computer Science A • Class Variables and Methods