Ten lessons that follow the four course units in Java: objects and methods, selection and iteration, class creation and data collections, with tracing and free-response habits.
A reasoning guide to AP Computer Science A, not a full programming course. Unit order and weightings follow the College Board course page; all code examples are original and invented for practice.
No prior programming needed, but basic algebra helps.
Course outline
Variables, types and expressions
Trace code that uses int, double, boolean and String values, including integer division and casting.
Objects, classes and method calls
Create objects, call methods on them and understand references and null.
Boolean logic and if statements
Evaluate compound conditions and trace if, else if and else chains.
Loops: while and for
Trace loops, count iterations and avoid off-by-one and infinite loops.
Writing classes: fields, constructors and methods
Design a class with private fields, constructors and accessor and mutator methods.
Inheritance, polymorphism and static
Use extends, super and overriding, and predict which method runs.
Arrays and ArrayList
Traverse and modify arrays and ArrayLists, and use the right methods.
2D arrays, searching and sorting
Traverse 2D arrays by row and column and trace linear search, binary search and sorts.
Recursion and the call stack
Trace recursive methods, find base cases and avoid infinite recursion.
Exam day: reading specifications and writing methods
Use the exam format and the four free-response types to plan and check your code.
Sources and curriculum note
Reviewed October 5, 2026. Confirm format and the Java subset on the College Board site for your exam year.
Read every lesson below. The interactive reader above contains the same explanations, with visual tools and quizzes.
1. Variables, types and expressions
Learning goal: Trace code that uses int, double, boolean and String values, including integer division and casting.
AP Computer Science A uses Java. Unit 1 starts with primitive types: int for whole numbers, double for decimals and boolean for true or false. A variable has a type, a name and a value, and the type decides what operations are legal. Reference types such as String hold references to objects, not the object bytes themselves, which matters when you compare them.
Arithmetic follows precedence: multiplication, division and remainder before addition and subtraction, left to right at equal level. When both operands are int, division discards the fraction, so 7 / 2 is 3, and 7 % 2 is 1. If either operand is a double, the result is a double, so 7 / 2.0 is 3.5. A cast changes the type for one expression: (double) 7 / 2 casts first and gives 3.5, but (double) (7 / 2) divides first and gives 3.0.
Assignment copies the value on the right into the variable on the left. Compound operators such as x += 3 and x++ are shorthand. An int has a fixed range, and arithmetic that goes past the maximum wraps around to a negative number, which is an overflow bug. Ranges are fixed by the language, so check the Java documentation for exact limits. Constants are declared with final and cannot change after assignment.
When tracing code, keep a table of variable names and update the value after each line. Pay attention to where the cast is placed and what is an integer expression. Good habits for the exam: name variables for meaning, write a type for every variable and read the whole expression before computing. Questions often ask for the value printed or the value of a variable after several statements, so a trace table is faster and safer than doing it in your head. Examples here are invented for practice.
Worked example
Given int a = 10; int b = 4; double c = a / b; what does c hold?
a / b uses two ints, so integer division.
10 / 4 is 2.
The int 2 is stored in a double as 2.0.
c holds 2.0, not 2.5.
Practice problem and solution
What is the value of 17 % 5 ? Enter a number.
17 divided by 5 is 3 remainder 2.
Mental model: Integer division truncates. Casts apply to the next value only.
Common trap: Assuming dividing two ints gives a decimal.
2. Objects, classes and method calls
Learning goal: Create objects, call methods on them and understand references and null.
Unit 1 also covers using objects. A class is a blueprint; an object is one instance made with new. A constructor call such as new Rectangle(3, 4) creates the object and returns a reference to it. A variable of a class type holds a reference, and two variables can refer to the same object. If a reference variable holds null, it refers to nothing, and calling a method on it causes a NullPointerException.
Methods are called with dot notation: obj.area(). Some methods return a value and some are void, which return nothing and so cannot be used in an expression. Arguments are matched to parameters by order and type. A static method belongs to the class and is called with the class name, like Math.sqrt(16). The Math class is part of the course and has abs, pow, sqrt and random.
Strings are objects with methods. length() returns the number of characters, substring(a, b) returns characters from index a up to but not including b, and indexOf returns the first position or −1 when absent. Indexes start at 0. Strings are immutable: methods return new strings and never change the original. To compare content use equals, not ==, because == compares references.
When tracing method calls, note what is returned and what is stored. A common mistake is to call s.toUpperCase() and expect s to change; the new string must be assigned. Another is to pass fewer or different arguments than the method expects, which fails to compile. Read the method headers from the provided documentation on the exam, and treat each method as a black box with a defined input and output. The examples here are invented for practice.
Worked example
Given String s = "computer"; what does s.substring(3, 6) return?
Indexes: c0 o1 m2 p3 u4 t5 e6 r7.
The substring starts at index 3.
It stops before index 6.
It returns "put".
Practice problem and solution
What does "banana".indexOf("n") return? Enter a number.
Learning goal: Evaluate compound conditions and trace if, else if and else chains.
Unit 2 carries 25% to 35% of the multiple-choice section. Conditions are boolean expressions built from relational operators (<, >, ==, !=) and logical operators && (and), || (or) and ! (not). Operator precedence puts ! first, then &&, then ||. Use parentheses to make the intended order clear.
Java uses short-circuit evaluation. In a && b, if a is false then b is not evaluated; in a || b, if a is true then b is skipped. That lets you write x != 0 && 10 / x > 1 without a divide-by-zero error. De Morgan's laws help simplify negations: !(a && b) equals !a || !b, and !(a || b) equals !a && !b.
An if statement runs its block when the condition is true. An else runs when it is false. In an if, else if, else chain, only the first branch whose condition is true runs. If you write separate if statements instead, each is tested independently and several blocks can run. Check the order of conditions: a broad condition first can hide a narrower one that follows.
Common bugs include using = instead of ==, forgetting braces so only one statement belongs to the if, and writing a condition that is always true, such as x > 5 || x < 10. For a range check use &&: x > 5 && x < 10. To test a condition, try boundary values: the exact limit, one below and one above. Examples here are invented for practice.
Worked example
Given int x = 7; what does (x > 5 && x < 10) || x == 0 evaluate to?
x > 5 is true.
x < 10 is true.
true && true is true.
true || anything is true, so the result is true.
Practice problem and solution
How many branches of an if, else if, else chain run when the first condition is true? Enter a number.
Only the first true branch runs.
Mental model: Short-circuit logic, De Morgan and exclusive chains.
Common trap: Using || for a range check that needs &&.
4. Loops: while and for
Learning goal: Trace loops, count iterations and avoid off-by-one and infinite loops.
Loops repeat code. A while loop tests its condition before each pass and may run zero times. A for loop packs initialisation, condition and update into one header: for (int i = 0; i < 5; i++) runs with i equal to 0, 1, 2, 3, 4, which is five passes. The loop variable is usually visible only inside the loop. If the update never makes the condition false, the loop never ends.
To count iterations, subtract the start from the stop and watch the operator. With i < n starting at 0 there are n passes; with i <= n there are n + 1. Off-by-one errors are the most common loop bug. For loops that step by more than one, such as i += 2, divide and round up. Test small cases by hand, including the case where the loop should run zero times.
Loops are used for accumulation, search and counting. An accumulator such as sum += i adds each value. A counter increments when a condition is true. Searching loops stop early when a value is found, using return inside a method or a flag. String traversal loops through each index from 0 to length() - 1 with charAt or substring(i, i + 1).
Nested loops run the inner loop completely for each pass of the outer loop, so the total passes multiply. A loop with 3 outer and 4 inner passes runs the inner body 12 times. Trace nested loops with a table showing both variables. In free-response questions you are often asked to write a loop that processes values and returns a result, so practise the pattern: initialise, loop, update the accumulator, return it. Examples here are invented for practice.
Worked example
How many times does the body run for (int i = 2; i <= 10; i += 2)?
Values of i: 2, 4, 6, 8, 10.
Each satisfies i <= 10.
The next value, 12, fails.
The body runs 5 times.
Practice problem and solution
A nested loop has an outer loop of 3 passes and an inner loop of 4 passes. How many times does the inner body run?
5. Writing classes: fields, constructors and methods
Learning goal: Design a class with private fields, constructors and accessor and mutator methods.
Unit 3 carries 10% to 18% of the multiple-choice section and is the basis of free-response Question 2, class design. A class has instance variables (fields), constructors and methods. Instance variables are usually private so outside code cannot change them directly, which is encapsulation. Public methods give controlled access: an accessor (getter) returns a value and a mutator (setter) changes it, perhaps after checking it is valid.
A constructor has the same name as the class, no return type, and sets up the fields. If you write no constructor, Java provides a default one with no parameters. When a parameter has the same name as a field, this.name = name uses this to refer to the field. Each object has its own copy of the instance variables, while a static variable is shared by all objects of the class.
A method header lists access, return type, name and parameters: public double getBalance(). A method with a return type must return a value on every path. Parameters are passed by value: the method gets a copy of a primitive, or a copy of a reference to an object, so reassigning the parameter does not change the caller's variable, though changing the object's state through the reference does. Local variables exist only while the method runs.
For the class design question, read the specification table closely. Write the class header, the private instance variables, the constructor and each required method, in that order. Check that each method returns the type stated and that the constructor initialises every field. Add a toString method if asked, returning a String. Do not add features the specification does not request. Examples here are invented for practice.
Worked example
Describe the class members needed for a Counter that starts at 0, can be incremented and can report its value.
Private int count as the instance variable.
Constructor sets count to 0.
A void increment method does count++.
An int getCount method returns count.
Practice problem and solution
How many return values can a single method call return? Enter a number.
A method returns at most one value, though that value can be an object holding several.
Mental model: Private fields, public methods, constructor sets up state.
Common trap: Forgetting to initialise a field in the constructor.
6. Inheritance, polymorphism and static
Learning goal: Use extends, super and overriding, and predict which method runs.
Inheritance lets a subclass reuse and extend a superclass. The keyword extends declares the relationship, and the subclass inherits public and protected members. A subclass constructor calls super(...) first to set up the inherited part. Overriding means writing a method in the subclass with the same name and parameters as one in the superclass, so the subclass supplies its own behaviour. The subclass method can still call the original with super.method().
Polymorphism means a variable of a superclass type can refer to an object of a subclass. When a method is called, the version that runs is decided by the actual object type, not the variable type, but the code compiles only if the variable's type has that method. So Animal a = new Dog(); lets you call a.speak() and runs Dog's version if Dog overrides it, but a.fetch() fails to compile if only Dog has fetch.
Every class inherits from Object, including toString and equals. Overriding toString controls how an object prints. Static methods belong to the class and cannot use instance variables directly. Check the College Board course description for which Java features are in scope for your exam year. Overloading, in contrast, means several methods with the same name but different parameter lists in one class.
When tracing, find the declared type, find the actual type, check whether the method exists in the declared type, then run the actual type's version. Draw the class hierarchy as a small box diagram with the methods each class defines. Subclass constructors must handle any superclass constructor that needs arguments. The examples here are invented for practice.
Worked example
Animal has speak() printing "..."; Dog overrides it to print "Woof". What prints for Animal a = new Dog(); a.speak();?
The declared type Animal has speak, so it compiles.
The actual object is a Dog.
Dog overrides speak.
It prints Woof.
Practice problem and solution
In a subclass constructor, which call must come first to set up the parent part? Type super.
super(...) runs the superclass constructor first.
Mental model: Declared type compiles, actual type runs.
Common trap: Calling a subclass-only method through a superclass variable.
7. Arrays and ArrayList
Learning goal: Traverse and modify arrays and ArrayLists, and use the right methods.
Unit 4 carries 30% to 40% of the multiple-choice section, the largest share. An array has a fixed length set when it is created, and its elements are accessed by index from 0 to length - 1. Note that length is a field, written without parentheses. Going past the end throws an ArrayIndexOutOfBoundsException. An ArrayList grows and shrinks, uses size(), get(i), set(i, x), add(x), add(i, x) and remove(i).
An enhanced for loop, for (int v : arr), visits each element in order. It is read only for primitives, since changing v does not change the array. Use a standard indexed loop when you need the position or to modify elements. Typical algorithms are summing, finding a maximum, counting matches and shifting elements.
Removing from an ArrayList while looping forward is a classic bug. After remove(i) the later elements shift left, so the element that moved into position i is skipped when the loop increments i. Fixes are to loop backwards or to decrement i after a removal. Inserting with add(i, x) shifts later elements right. An ArrayList stores objects, so primitives are wrapped as Integer or Double, and the compiler converts automatically.
For free-response Question 3, you write a method that uses an ArrayList: read the specification, decide on the loop, handle the empty list and return the correct type. Test with a list of 0, 1 and 2 items by hand. Remember that list.get(i) returns an object, so compare objects with equals. Examples here are invented for practice.
Worked example
Given int[] a = {4, 9, 2}; what does a[a.length - 1] hold and what does a[3] cause?
a.length is 3, so a[2] is the last element.
a[2] holds 2.
Valid indexes are 0 to 2.
a[3] throws an ArrayIndexOutOfBoundsException.
Practice problem and solution
An ArrayList has 5 elements and you call remove(0). What is its size afterwards?
Removing one element leaves 4.
Mental model: Indexes shift on add and remove. Mind length versus size().
Common trap: Skipping elements by removing in a forward loop.
8. 2D arrays, searching and sorting
Learning goal: Traverse 2D arrays by row and column and trace linear search, binary search and sorts.
A 2D array is an array of arrays. grid.length is the number of rows and grid[0].length is the number of columns. Row-major traversal uses an outer loop over rows and an inner loop over columns. Column-major traversal swaps them. Free-response Question 4 uses a 2D array, so practise sums by row, sums by column and finding the largest value with its position.
Linear search checks each element in turn and works on any list. Binary search needs a sorted list: compare the target with the middle element, discard the half that cannot contain it and repeat. Each step halves the remaining range, so a sorted list of 1,000 items needs about 10 comparisons, since 2 to the power 10 is 1,024. Binary search on unsorted data gives wrong answers.
Selection sort finds the smallest remaining element and swaps it into the next position. Insertion sort takes each element in turn and slides it left into its place among the already sorted ones. Both need about n squared steps in the worst case, so they are slow for large lists, but they are easy to trace. Merge sort splits the list in half, sorts each half recursively and merges them, and is much faster for large lists.
Recursion appears in the course too: a method that calls itself needs a base case that stops it and a recursive case that moves toward the base case. Trace a recursive call with a stack of pending calls. Check for infinite recursion when the argument does not get closer to the base case. Examples here are invented for practice.
Worked example
Trace selection sort on {5, 2, 8, 1} for the first pass.
Find the smallest in the whole list: 1 at index 3.
Swap with index 0.
The list becomes {1, 2, 8, 5}.
The first position is now final; repeat on the rest.
Practice problem and solution
A 2D array has 3 rows and 4 columns. What does grid[0].length return?
grid[0] is the first row, and its length is the number of columns, 4.
Mental model: Rows then columns. Binary search needs sorted data.
Common trap: Using binary search on an unsorted list.
9. Recursion and the call stack
Learning goal: Trace recursive methods, find base cases and avoid infinite recursion.
A recursive method calls itself on a smaller version of the problem. Every correct recursive method has a base case that returns an answer without another call, and a recursive case that moves toward the base case. A classic example is factorial: the base case is that factorial of 0 is 1, and the recursive case is n times factorial of n minus 1. If the argument never reaches the base case, the calls never stop and the program fails with a stack overflow error.
Each call gets its own copy of the parameters and local variables. Calls wait on a stack: the newest call runs first, and when it returns, the one below it continues with the returned value. To trace a recursive method, write each call on its own line with its argument, go down until the base case, then work back up filling in return values. Writing both the way down and the way up avoids most mistakes.
The position of a print statement changes the output. A print before the recursive call shows values on the way down, in order of the calls. A print after the call shows values on the way back up, in reverse order. Questions often ask for the exact printed sequence, so decide first whether a statement runs before or after the call. A method that returns a value must use the returned value, for example by adding it to something, or the work is lost.
Recursion and loops can often do the same job. Recursion can be clearer for problems that split into smaller copies, such as binary search or merge sort, but each call uses memory. When asked to write a recursive method, write the base case first, then the recursive case, and test with the smallest input. Examples here are invented for practice.
Worked example
With f(n) returning 1 if n is 0, otherwise n times f(n - 1), compute f(3).
f(3) = 3 × f(2).
f(2) = 2 × f(1), and f(1) = 1 × f(0).
f(0) is the base case and returns 1.
f(1) = 1, f(2) = 2, f(3) = 6.
Practice problem and solution
Using the same f, what is f(4)? Enter a number.
4 × 3 × 2 × 1 = 24.
Mental model: Base case, recursive case, trace down and back up.
Common trap: Forgetting that code after the call runs on the way back.
10. Exam day: reading specifications and writing methods
Learning goal: Use the exam format and the four free-response types to plan and check your code.
The College Board's AP Computer Science A exam page lists two sections. Section I has 42 multiple-choice questions in 1 hour 30 minutes, worth 55% of the exam score. Section II has four free-response questions in 1 hour 30 minutes, worth 45%. The questions are: methods and control structures, class design, data analysis with ArrayList and 2D array. Check the exam page for your year, since format and policies can change.
The course framework lists five computational thinking practices: design code, develop code, analyse code, document code and computing systems, and use computers responsibly. Analysing code carries the largest share of the multiple-choice section, 37% to 53%, according to the course page. That means tracing and predicting output is the most tested skill, so practise with a trace table until it is routine.
In the free response, read the specification and the examples first and note exact method names, parameter types and return types. Write only the requested method or class, using the provided methods and not rewriting them. Use the right loop for the structure, handle the empty case and return the right type. Partial credit comes from specific features such as correct loop bounds, correct accumulation and correct return, so write each part clearly even when unsure about the rest.
Check your answer against the examples in the problem by tracing at least one by hand. Check for common errors: off-by-one bounds, using == on Strings, missing return, wrong variable scope, modifying a list while looping forward, and calling a method on the class instead of an object. Write neat code with consistent indentation so a grader can read it. Do not worry about minor syntax like a missing semicolon more than about logic, but do not rely on that leniency. Examples here are invented for practice.
Worked example
Plan a method that returns the number of negative values in an int array.
Declare int count = 0.
Loop through every index of the array.
If the element is less than 0, increment count.
After the loop, return count.
Practice problem and solution
How many free-response questions are on the exam? Enter a number.
Four, according to the College Board exam page.
Mental model: Read the spec, plan, trace, return the right type.
Common trap: Rewriting provided methods instead of calling them.