AP CSA Unit 3 Study Guide | Class Creation 2025-2026
AP CSA Unit 3 Study Guide 2026 | Class Creation & OOP
AP Computer Science A
Complete Study Guide — 2025-2026 Curriculum
📚 Unit Overview
In Units 1 and 2, you learned to use existing classes like String and Math. Now it's time to become the architect—Unit 3 teaches you to design and build your own classes from scratch.
This is where object-oriented programming comes alive. Instead of just writing procedures that manipulate data, you'll create blueprints that bundle data and behavior together.
What You'll Learn
- Design classes that model real-world entities
- Write constructors that properly initialize objects
- Implement methods that access and modify object state
- Apply encapsulation to protect data
- Use static variables and methods appropriately
- Understand scope rules and the
thiskeyword
Unit 3 Topics at a Glance
| Topic | Description | Exam Weight |
|---|---|---|
| Abstraction | Program design and modeling real-world entities | Medium |
| Instance Variables | Declaring and using object attributes | High |
| Constructors | Initializing objects, overloading | High |
| Methods | Accessors, mutators, other behaviors | High |
| Encapsulation | Private variables, public methods | High |
| Static Members | Class variables and methods vs instance | Medium |
| Scope | Variable visibility and lifetime | Medium |
| this Keyword | Referencing the current object | Medium |
🏗 Anatomy of a Class
Every Java class follows a consistent structure. The class is the blueprint; objects are the actual things built from that blueprint.
public class Student
{
// ========== INSTANCE VARIABLES ==========
private String name;
private int idNumber;
private double gpa;
// ========== CONSTRUCTOR ==========
public Student(String studentName, int id)
{
name = studentName;
idNumber = id;
gpa = 0.0;
}
// ========== METHODS ==========
public String getName()
{
return name;
}
public void setGpa(double newGpa)
{
gpa = newGpa;
}
public double getGpa()
{
return gpa;
}
}
The Four Components
| Component | Purpose | Access Modifier |
|---|---|---|
| Class Header | Declares the class name | public |
| Instance Variables | Store data for each object | private |
| Constructor(s) | Initialize new objects | public |
| Methods | Define object behaviors |
public (usually) |
Creating and Using Objects
// Creating Student objects
Student alice = new Student("Alice Johnson", 12345);
Student bob = new Student("Bob Smith", 12346);
// Each object has its own data
alice.setGpa(3.8);
bob.setGpa(3.2);
System.out.println(alice.getName()); // Alice Johnson
System.out.println(alice.getGpa()); // 3.8
System.out.println(bob.getGpa()); // 3.2
Student class, but you can create THOUSANDS of Student objects, each with its own name, ID, and GPA.📦 Instance Variables & Encapsulation
Instance variables store the data that each object needs. Every object created from a class gets its own copy of these variables.
Declaring Instance Variables
public class BankAccount
{
private String accountHolder;
private double balance;
private int accountNumber;
private boolean isActive;
}
Default Values
If you don't explicitly initialize an instance variable, Java assigns a default value:
| Data Type | Default Value |
|---|---|
int, long, short, byte
|
0 |
double, float
|
0.0 |
boolean |
false |
| Object references (String, etc.) | null |
Encapsulation: Why Private Matters
Encapsulation means hiding an object's internal data and only allowing access through controlled methods.
❌ Without Encapsulation
public double balance;
// Anyone can do this:
account.balance = -1000000;
// No validation!
✓ With Encapsulation
private double balance;
public void withdraw(double amt) {
if (amt > 0 && amt <= balance)
balance -= amt;
}
public on the AP Exam. The scoring guidelines specifically check for this, and you will lose points.🔨 Constructors
A constructor is a special method that runs automatically when you create a new object using new. Its job is to initialize the object's instance variables.
Constructor Rules
| Rule | Correct | Wrong |
|---|---|---|
| Name must match class name | public Student(...) |
public student(...) |
| No return type (not even void) | public Student(...) |
public void Student(...) |
| Usually public | public Student(...) |
private Student(...) |
public void Rectangle(...) creates a regular method named Rectangle, NOT a constructor. No return type means no return type—not even void.Writing Constructors
public class Rectangle
{
private double width;
private double height;
// Constructor - NO return type!
public Rectangle(double w, double h)
{
width = w;
height = h;
}
}
// Creating objects:
Rectangle r1 = new Rectangle(5.0, 3.0);
Rectangle r2 = new Rectangle(10.0, 2.5);
Constructor Overloading
A class can have multiple constructors with different parameter lists:
public class Rectangle
{
private double width;
private double height;
// Constructor 1: Takes width and height
public Rectangle(double w, double h)
{
width = w;
height = h;
}
// Constructor 2: Creates a square
public Rectangle(double side)
{
width = side;
height = side;
}
// Constructor 3: Default 1x1
public Rectangle()
{
width = 1.0;
height = 1.0;
}
}
// All three work:
Rectangle r1 = new Rectangle(5.0, 3.0); // Uses Constructor 1
Rectangle r2 = new Rectangle(4.0); // Uses Constructor 2
Rectangle r3 = new Rectangle(); // Uses Constructor 3
⚙ Writing Methods
Methods define what an object can do—its behaviors.
Method Structure
| Part | Example | Meaning |
|---|---|---|
| Access modifier | public |
Who can call this method |
| Return type | double |
What type of value it gives back |
| Method name | getArea |
How you call it |
| Parameters | () |
What inputs it needs |
Accessor Methods (Getters)
Return the value of an instance variable without modifying it:
public String getName()
{
return name;
}
public double getBalance()
{
return balance;
}
// For booleans, use "is" prefix
public boolean isActive()
{
return isActive;
}
Mutator Methods (Setters)
Change the value of an instance variable:
public void setName(String newName)
{
name = newName;
}
// Setter with validation
public void setGpa(double newGpa)
{
if (newGpa >= 0.0 && newGpa <= 4.0)
{
gpa = newGpa;
}
}
Methods That Return Values vs Void
// Returns a value - must have return statement
public double getArea()
{
return width * height;
}
// Void method - performs action, returns nothing
public void printInfo()
{
System.out.println("Width: " + width);
System.out.println("Height: " + height);
// No return statement needed
}
⚙ toString() and equals()
These two methods appear on nearly every FRQ Q2. You must be able to write both from scratch, recognize their signatures instantly, and understand how Java calls them automatically.
The toString() Method
toString() defines how an object looks when printed or concatenated with a String. Java calls it automatically whenever you use an object in a String context.
public class Point
{
private int x;
private int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Correct toString signature: public String toString()
public String toString()
{
return "(" + x + ", " + y + ")";
}
}
Point p = new Point(3, 7);
System.out.println(p); // (3, 7) — calls toString() automatically
System.out.println("At: " + p); // At: (3, 7) — concatenation triggers toString()
String s = p.toString(); // explicit call also works
Writing public void toString() — returns nothing. Or public String toString(int x) — wrong signature, never called automatically. The only correct signature is:
public String toString() // no parameters, returns String
The equals() Method
equals() defines what it means for two objects to be "the same." Without it, == only checks if two variables point to the same object in memory — it will never be true for two separately constructed objects even if they hold identical data.
public class Student
{
private String name;
private int id;
public Student(String name, int id)
{
this.name = name;
this.id = id;
}
// Correct equals signature: public boolean equals(Object other)
public boolean equals(Object other)
{
if (!(other instanceof Student)) return false;
Student s = (Student) other; // cast to access fields
return this.id == s.id; // define equality by ID
}
}
Student a = new Student("Alice", 101);
Student b = new Student("Alice", 101);
System.out.println(a == b); // false — different objects in memory
System.out.println(a.equals(b)); // true — same id, so equals() says yes
toString() vs equals() Side-by-Side
| Property | toString() | equals() |
|---|---|---|
| Return type | String |
boolean |
| Parameter | none | Object other |
| When auto-called | Printing, concatenation | Never — must call explicitly |
| What it defines | Text representation | Content equality |
| Without it | Prints memory address like Student@6d06d69c
|
== only checks reference |
- Correct method signature (exact return type and parameter list)
-
toString()must return a String, not print one -
equals()must acceptObjectparameter (notStudent), then cast - Accessing instance variables through the cast object (
s.id, notother.id) - Returning a boolean expression, not assigning it
toString() and equals() in Practice — MCQ Traps
// Trap 1: What does this print?
Point p1 = new Point(2, 5);
Point p2 = p1; // p2 is an ALIAS for p1
System.out.println(p1 == p2); // true — same object reference
System.out.println(p1.equals(p2)); // true — same object, so equal
// Trap 2: equals() not overridden — falls back to == behavior
public class Box { private int size; } // no equals() defined
Box b1 = new Box(); // size = 0
Box b2 = new Box(); // size = 0
System.out.println(b1.equals(b2)); // false! No override, uses Object.equals() = ==
🔒 Static Variables and Methods
Sometimes you need something that belongs to the class itself and is shared by all objects. This is what static is for.
Static Variables (Class Variables)
public class Student
{
private String name; // Instance - each Student has own
private static int totalStudents = 0; // Static - shared by ALL
public Student(String name)
{
this.name = name;
totalStudents++; // Increment shared counter
}
public static int getTotalStudents()
{
return totalStudents;
}
}
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
System.out.println(Student.getTotalStudents()); // 2
Static vs Instance Comparison
| Instance | Static | |
|---|---|---|
| Belongs to | Each individual object | The class itself |
| How many copies | One per object | One total (shared) |
| How to access | objectName.method() |
ClassName.method() |
| Can access instance variables? | Yes | No! |
public static void printBalance() {
System.out.println(balance); // ERROR!
}
👆 The this Keyword
The keyword this is a reference to the current object — the specific instance that is running the method. It has three uses on the AP exam.
Use 1: Resolve Parameter Shadowing (Most Common)
When a constructor or method parameter has the same name as an instance variable, this disambiguates them:
public class Student
{
private String name;
private int grade;
public Student(String name, int grade)
{
this.name = name; // this.name = instance var, name = parameter
this.grade = grade; // this.grade = instance var, grade = parameter
}
}
public Student(String name, int grade)
{
name = name; // Assigns parameter to itself — does NOTHING!
grade = grade; // Instance variables stay null and 0
}
The instance variable is never assigned. Any call to getName() after this constructor returns null.
Use 2: Pass the Current Object to Another Method
this can be passed as an argument when a method expects an object of the same type:
public class BankAccount
{
private double balance;
public void transferTo(BankAccount target, double amount)
{
balance -= amount;
target.balance += amount;
}
public void selfTransferTest()
{
transferTo(this, 100.0); // passes current object as "target"
}
}
Use 3: Implicit vs Explicit this
Inside any instance method, this.variable and just variable mean the same thing — as long as there is no local variable with that name. The AP exam does not require you to write this when it is not needed, but you will never lose points for including it:
public double getBalance()
{
return balance; // implicit this — fine
// return this.balance; — also fine, same result
}
- Parameter or local variable shadows the instance variable — use
this.field - Passing the current object to another method — use
thisas the argument - Any other time: optional but acceptable
🔍 Scope, Access & Objects as Parameters
Scope determines which variable a name refers to. Getting this wrong is the source of several common FRQ mistakes and a frequent MCQ trap. Objects as method parameters have behavior that surprises most students.
Scope: Local Variables vs Instance Variables
A local variable exists only inside the method where it is declared. An instance variable exists for the lifetime of the object. When both have the same name, the local variable shadows the instance variable.
public class Scoreboard
{
private int score; // instance variable
public void addPoints(int score) // parameter also named "score"
{
score = score + 10; // BUG: assigns parameter to itself!
// The instance variable is never touched.
}
public void addPointsFixed(int points)
{
score = score + points; // ✔ Different name, no ambiguity
}
public void addPointsThis(int score)
{
this.score = this.score + score; // ✔ this.score = instance, score = param
}
}
Block Scope
Variables declared inside a loop or if block only exist inside that block:
public int countPositive(int[] arr)
{
int count = 0; // method scope — visible throughout method
for (int i = 0; i < arr.length; i++)
{
int val = arr[i]; // block scope — only exists inside for loop
if (val > 0) count++;
}
// val is NOT accessible here — compiler error if you try
return count;
}
Objects as Parameters — Pass by Reference
When you pass a primitive to a method, the method gets a copy — the original is unchanged. When you pass an object, the method gets a reference to the same object — changes to fields do affect the original.
// Primitives: original unchanged
public static void doubleIt(int n)
{
n = n * 2; // only changes local copy
}
int x = 5;
doubleIt(x);
System.out.println(x); // still 5 — original unchanged
// Objects: original CAN change via mutators
public static void resetScore(Scoreboard sb)
{
sb.setScore(0); // modifies the actual Scoreboard object
}
Scoreboard board = new Scoreboard(100);
resetScore(board);
System.out.println(board.getScore()); // 0 — the original was modified
You can modify an object's fields through a method parameter, but you cannot make the calling code's variable point to a different object:
public static void replace(Scoreboard sb)
{
sb = new Scoreboard(999); // only changes local copy of the reference
}
Scoreboard board = new Scoreboard(100);
replace(board);
System.out.println(board.getScore()); // still 100 — board was NOT replaced
Returning Objects from Methods
Methods can return objects just like primitives. The return type is the class name:
public class Rectangle
{
private double width, height;
public Rectangle(double w, double h) { width = w; height = h; }
// Returns a new Rectangle that is twice as wide
public Rectangle doubleWidth()
{
return new Rectangle(width * 2, height);
}
public double getWidth() { return width; }
}
Rectangle r = new Rectangle(5.0, 3.0);
Rectangle wider = r.doubleWidth();
System.out.println(wider.getWidth()); // 10.0
System.out.println(r.getWidth()); // 5.0 — original unchanged
Helper (Private) Methods
A method can call other methods from the same class. Private helper methods do work that no outside code needs to access directly:
public class GradeCalculator
{
private double total;
private int count;
// Private helper — only used inside this class
private double computeAverage()
{
if (count == 0) return 0.0;
return total / count;
}
// Public method calls the private helper
public String getLetterGrade()
{
double avg = computeAverage(); // calling private helper
if (avg >= 90) return "A";
if (avg >= 80) return "B";
return "C";
}
}
- When a method spec says "use your answer from Part (a)," you are calling a helper method you already wrote
- You earn points for calling it correctly, not re-implementing its logic
- Always call
computeAverage(), notthis.computeAverage()— both work, but the shorter form is cleaner and earns full credit
⚠ Common Errors (Don't Lose Points!)
The College Board scoring commentaries reveal the same mistakes year after year:
Error 1: Adding Return Type to Constructor
❌ WRONG
public void Rectangle(double w)
{
width = w;
}
// This is a METHOD, not a constructor!
✓ CORRECT
public Rectangle(double w)
{
width = w;
}
// No return type at all
Error 2: Public Instance Variables
❌ WRONG
public String name;
public double balance;
✓ CORRECT
private String name;
private double balance;
Error 3: Forgetting this with Shadowed Names
❌ WRONG
public Point(int x, int y)
{
x = x; // Does nothing!
y = y; // Does nothing!
}
✓ CORRECT
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
Error 4: Wrong Return Type
If spec says "returns the area," you need public double getArea(), NOT public void getArea()!
Error 5: Static Method Accessing Instance Variable
public static void printInfo()
{
System.out.println(name); // ERROR! Can't access instance var from static
}
📝 FRQ Question 2 Preparation
Question 2 is the Class Design question. You'll write a complete class from specifications.
Step-by-Step Approach
Step 1: Write the Class Header
public class ClassName
{
Step 2: Declare Instance Variables (all private!)
private Type1 variable1;
private Type2 variable2;
Step 3: Write the Constructor (NO return type!)
public ClassName(parameters)
{
// Initialize ALL instance variables
}
Step 4: Write Each Required Method
public ReturnType methodName(parameters)
{
// Implementation
}
}
FRQ Checklist
- ☐ Class header is
public class ClassName - ☐ All instance variables are
private - ☐ Constructor has NO return type
- ☐ Constructor is
public - ☐ Constructor initializes ALL instance variables
- ☐ Each method has correct return type
- ☐ Methods that return values have
returnstatement - ☐ Used
thiswhere parameter names match instance variables
📝 Practice Questions
Question 1
What is printed by the following code?
public class Counter
{
private int count;
public Counter() { count = 0; }
public void increment() { count++; }
public int getCount() { return count; }
}
Counter c1 = new Counter();
Counter c2 = new Counter();
c1.increment();
c1.increment();
c2.increment();
System.out.println(c1.getCount() + " " + c2.getCount());
Each object has its own
count. c1 is incremented twice (0→1→2), c2 once (0→1). Objects are independent.Question 2
Which is a valid constructor for a class named Book?
Constructors have no return type (A has void), must match the class name, and are typically public.
Question 3
What is printed?
public class Point
{
private int x;
private int y;
public Point(int x, int y)
{
x = x;
y = y;
}
public int getX() { return x; }
public int getY() { return y; }
}
Point p = new Point(5, 10);
System.out.println(p.getX() + " " + p.getY());
Classic shadowing bug!
x = x; assigns the parameter to itself—instance variables stay at default 0. Fix: this.x = x;
Question 4
Consider this class:
public class Tracker
{
private static int total = 0;
private int id;
public Tracker() { total++; id = total; }
public int getId() { return id; }
public static int getTotal() { return total; }
}
Tracker t1 = new Tracker();
Tracker t2 = new Tracker();
Tracker t3 = new Tracker();
System.out.println(t1.getId() + " " + t2.getId() + " " + Tracker.getTotal());
Static
total is shared. Each constructor increments it (1, 2, 3) and stores the current value in that object's id.Question 5
Which statement about encapsulation is TRUE?
Encapsulation = private instance variables + public methods for controlled access.
Question 6
What is the default value of an uninitialized String instance variable?
All object references default to
null. Note: null ≠ empty string "".FRQ Practice: Write a Complete Class
Write a complete BankAccount class with:
- Instance variables:
balance(double),accountId(String) - Constructor that takes an accountId and initializes balance to 0
- Method
deposit(double amount)that adds to balance (if amount > 0) - Method
getBalance()that returns the balance
public class BankAccount
{
private double balance;
private String accountId;
public BankAccount(String id)
{
accountId = id;
balance = 0;
}
public void deposit(double amount)
{
if (amount > 0)
{
balance = balance + amount;
}
}
public double getBalance()
{
return balance;
}
}
📋 Quick Reference
Class Template
public class ClassName
{
// Instance variables (PRIVATE)
private Type variableName;
// Constructor (NO return type)
public ClassName(parameters)
{
// Initialize variables
}
// Accessor (getter)
public Type getVariableName()
{
return variableName;
}
// Mutator (setter)
public void setVariableName(Type newValue)
{
variableName = newValue;
}
}
Default Values
| Type | Default |
|---|---|
int |
0 |
double |
0.0 |
boolean |
false |
| Objects (String, etc.) | null |
Common Mistakes Checklist
| Mistake | Fix |
|---|---|
public void ClassName() |
Remove void
|
public String name; |
Change to private
|
name = name; |
Use this.name = name;
|
| Static method uses instance var | Make method non-static or var static |
Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
tanner@apcsexamprep.com
Courses
AP CSA, CSP, & Cybersecurity
Response Time
Within 24 hours
Prefer email? Reach me directly at tanner@apcsexamprep.com
Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
tanner@apcsexamprep.com
Courses
AP CSA, CSP, & Cybersecurity
Response Time
Within 24 hours
Prefer email? Reach me directly at tanner@apcsexamprep.com