🤖 AP CSA Lab - Classes & Methods

Five days, one file, one certificate at the end. Each day builds on real Java classes - reading them, predicting what they'll do, then writing your own.

📄 Java Quick Reference Sheet

Day 1 - Reading a Real Class

Here's the full Robot class. Notice it has public methods (callable from anywhere), a private method (only callable from inside the class itself), overloaded constructors and an overloaded move() method (same name, different parameter lists), and static factory methods that build a Robot without needing one to already exist.

public class Robot { private String name; private int x; private int y; private int energy; public Robot(String name) { this.name = name; this.x = 0; this.y = 0; this.energy = 100; } public Robot(String name, int startX, int startY) { this.name = name; this.x = startX; this.y = startY; this.energy = 100; } public void move(int dx, int dy) { x += dx; y += dy; energy -= (Math.abs(dx) + Math.abs(dy)); } public void move(String direction) { if (direction.equals("up")) { y += 1; } else if (direction.equals("down")) { y -= 1; } else if (direction.equals("left")) { x -= 1; } else if (direction.equals("right")) { x += 1; } energy -= 1; } private int distanceFromOrigin() { return Math.abs(x) + Math.abs(y); } public String status() { return name + " is at (" + x + ", " + y + ") with " + energy + " energy, " + distanceFromOrigin() + " steps from home."; } public int getEnergy() { return energy; } public static Robot createDefault() { return new Robot("Default"); } public static Robot createAt(int x, int y) { return new Robot("Unnamed", x, y); } }

For each item below: type your prediction first, then click Reveal - don't peek early, the whole point is predicting before you know.

Predict the Outcome (12 total)

You only get 4 reveals total, across all 12 items - pick them wisely. Type a real prediction for every one of the 12, but you can only check your answer against the correct one 4 times. Once you've used all 4, the Reveal button disappears everywhere - the rest you'll have to trust your own reasoning on, same as on exam day.

Day 1 Requirements

Day 2 - Math Methods in Action

Here's a Point class. Its methods lean on Math.sqrt, Math.pow, and Math.abs to calculate real distances between points. For each activity below, work out the number by hand and type it in - no multiple choice, just the actual math.

public class Point { private double x; private double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public double distanceFromOrigin() { return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); } public double distanceTo(Point other) { double dx = this.x - other.x; double dy = this.y - other.y; return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); } public double manhattanDistanceTo(Point other) { return Math.abs(this.x - other.x) + Math.abs(this.y - other.y); } public Point midpointTo(Point other) { return new Point((this.x + other.x) / 2, (this.y + other.y) / 2); } }

Answers are checked as numbers, so typing 5 or 5.0 both count - decimals within a small rounding tolerance are fine too.

Activities (10 total)

Day 2 Requirements

Day 3 - Complete the Slot Machine

Below is a SlotMachine class with 10 blanks, numbered /* BLANK N */ right where each one goes. Every blank only needs what you already know - assigning a field, calling an existing method, or writing a return. isJackpot() and randomSymbol() are already fully written for you, since they use if/else and array indexing you haven't covered yet - you're not expected to write those parts, just read them.

public class SlotMachine { private static String[] SYMBOLS = {"CHERRY", "LEMON", "BELL", "STAR", "DIAMOND"}; private String reel1; private String reel2; private String reel3; private int credits; private int spinCount; public SlotMachine(int startingCredits) { /* BLANK 1 */ /* BLANK 2 */ } // Given complete - uses array indexing, not covered yet private static String randomSymbol() { int index = (int)(Math.random() * SYMBOLS.length); return SYMBOLS[index]; } public void spin() { /* BLANK 3 */ /* BLANK 4 */ /* BLANK 5 */ /* BLANK 6 */ } // Given complete - uses if/else, not covered yet public boolean isJackpot() { if (reel1.equals(reel2) && reel2.equals(reel3)) { return true; } else { return false; } } public String getReel1() { /* BLANK 7 */ } public String getReel2() { /* BLANK 8 */ } public String getReel3() { /* BLANK 9 */ } // Bonus credits scale with how many times you've spun - same Math.pow from Day 2 public int bonusCredits() { /* BLANK 10 */ } public int getCredits() { return credits; } public int getSpinCount() { return spinCount; } }

Fill In The Blanks (10 total)

You get 2 hints total, across all 10 blanks - a hint reveals that blank's correct answer, so use them on the ones you're actually stuck on. Once both are used, the Hint button disappears everywhere.

Day 3 Requirements

Day 4 - Scope, Shadowing, and Access

Two classes, both with private/protected/public fields and methods, and a lot of variables deliberately reusing the same names (x, i) as fields, parameters, and loop variables. This is where scope rules actually matter - which variable does a bare name refer to when several are in play at once?

One honest note: "protected" isn't actually tested on the AP CSA exam (it only tests public/private) - it's included here as enrichment since you asked for it. Here, since nothing declares a package, protected behaves like same-file access, which is why main() can reach protected members directly but not private ones.

public class Box { private int x; protected int i; public int y; public Box(int x, int i) { this.x = x; this.i = i; this.y = 0; } public void increment() { int x = 5; this.x = this.x + x; y = y + 1; } private void loopA() { for (int x = 0; x < 3; x++) { y = y + x; } } public void runLoopA() { loopA(); } protected void loopB() { for (int x = 0; x < 2; x++) { this.x = this.x + 1; } } public int getX() { return this.x; } public int getI() { return i; } public int getY() { return y; } }
public class Counter { protected int x; private int i; public int total; public Counter(int x) { this.x = x; this.i = 0; this.total = 0; } public void tally(int x) { total = total + x; i = i + 1; } private int helper() { int i = 100; return i; } public int getHelperResult() { return helper(); } public int getX() { return x; } public int getI() { return i; } public int getTotal() { return total; } }
public class Main { public static void main(String[] args) { Box b = new Box(10, 1); Counter c = new Counter(5); b.increment(); c.tally(7); int helperResult = c.getHelperResult(); b.runLoopA(); b.loopB(); } }

Every question below traces through this exact sequence, in this exact order. Keep this code visible while you work.

Scope Challenge - get 20 in a row

Streak: 0 / 20
One wrong answer resets your streak to 0 - you have to string together 20 correct answers with no misses in between.

Day 4 Requirements

Day 5 - Write Your Own Class (FRQ Style)

Out of every method you could write, there are only two that are actually special this year - Java treats them differently from every ordinary method you write:

Constructors - they share the class's exact name, and have no return type at all, not even void. They run automatically the instant you write new.

toString() - Java calls this one automatically whenever you try to print an object directly, like System.out.println(myDog);. Without it, Java falls back to a meaningless default that just prints something like Dog@1a2b3c.

Every other method you write - accessors, mutators, static methods, anything else - is just an ordinary method with an ordinary name you chose yourself.

Worked Example - Dog

public class Dog { private String name; private int age; private String breed; // Constructor 1 - full information public Dog(String name, int age, String breed) { this.name = name; this.age = age; this.breed = breed; } // Constructor 2 - overloaded, breed defaults to "Unknown" public Dog(String name, int age) { this.name = name; this.age = age; this.breed = "Unknown"; } // Accessors public String getName() { return name; } public int getAge() { return age; } public String getBreed() { return breed; } // Mutators public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void setBreed(String breed) { this.breed = breed; } // Static method - doesn't need any particular Dog to run public static String describeSpecies() { return "Dogs are domesticated mammals, part of the wolf family."; } // toString - called automatically when a Dog gets printed directly public String toString() { return name + " is a " + age + " year old " + breed + "."; } }

Your Turn

Write your own class from scratch. Pick one of these, or a real-world idea of your own:

HouseCarYour own idea

Your class needs, at minimum:

  • At least 3 private fields that make sense for your theme
  • Two constructors (overloaded - different parameter lists, like the Dog example)
  • At least 2 accessor methods
  • At least 2 mutator methods
  • One static method
  • One toString() method

This page can only check that these pieces structurally appear to be present - it's not a compiler, so it can't verify your logic is actually correct. Mr. Wiessmann reads the real code for real credit, same as any FRQ.

Day 5 Requirements

Done for now? Check your work to see what's still missing and generate your certificate. You can check again anytime - only your best progress is kept.

Check your work above to unlock your certificate.
🏆
Certificate of Completion

This certifies that

Student