AP Computer Science A study package
Everything you need to prepare for the AP AP Computer Science A exam in one place: course overview, per-unit notes, practice sets, a full-length practice exam with answer key, and a printable summary sheet. Works alongside the timed AP Computer Science A practice exam and the score calculator.
Course overview
1AP Computer Science A — Complete Study Package Overview
The AP Computer Science A exam tests your understanding of Java programming fundamentals and your ability to solve problems using object-oriented programming. The exam is divided into two equally weighted sections, each worth 50% of your total score.
Section 1: Multiple-Choice Questions (MCQ)
- 40 questions in 90 minutes
- No calculators permitted
- Questions include standalone code analysis, class and method tracing, conceptual understanding, and scenario-based problem solving
- Approximately 60–65% of questions reference Java code snippets you must read and interpret
- Each question has five answer choices (A through E)
- There is no penalty for guessing — answer every question
Section 2: Free-Response Questions (FRQ)
- 4 questions in 90 minutes
- All questions require you to write Java code in response to a problem description
- You have access to the AP Java Quick Reference during this section
- FRQ 1: Methods and Control Structures — writing methods with loops, conditionals, and expressions
- FRQ 2: Classes — designing and implementing a class with constructors, methods, and instance variables
- FRQ 3: Array/ArrayList — processing data stored in arrays or ArrayLists using traversal and manipulation
- FRQ 4: 2D Array — working with two-dimensional arrays for table-like data processing
Both sections together total 3 hours. The exam is scored on a scale of 1–5, with a 5 being the highest possible score.
Java Quick Reference Sheet
The College Board provides a one-page reference sheet during both sections of the exam. It is critical that you know what is and is not on it. The reference sheet includes:
intanddoublearithmetic operations: addition, subtraction, multiplication, division, and modulo- Relational operators:
==,!=,<,>,<=,>= - Logical operators:
&&,||,! - String class methods:
length(),substring(int),substring(int, int),compareTo(),equals(),indexOf() - Integer class methods:
parseInt(),MAX_VALUE,MIN_VALUE - Double class methods:
parseDouble(),MAX_VALUE,MIN_VALUE - Math class methods:
abs(),pow(),sqrt(),random(),min(),max() - ArrayList class methods:
add(),remove(),get(),set(),size(),indexOf()The reference sheet does not include:
- Scanner methods, loop syntax, or array declaration syntax
Stringmethods such ascharAt(),toUpperCase(),toLowerCase(), orsubstringwith detailed parameter descriptions- Sorting or searching algorithm implementations
- Inheritance syntax or
superkeyword detailsYou must memorize syntax and concepts that are absent from the reference sheet.
Unit Breakdown
The AP CSA curriculum is organized into 10 instructional units:
| Unit | Topic | Approx. Exam Weight |
|---|---|---|
| 1 | Primitive Types | 2.5–5% |
| 2 | Using Objects | 5–7.5% |
| 3 | Boolean Expressions and If Statements | 7.5–10% |
| 4 | Iteration | 7.5–10% |
| 5 | Writing Classes | 10–15% |
| 6 | Arrays | 10–15% |
| 7 | ArrayList | 2.5–5% |
| 8 | 2D Arrays | 7.5–10% |
| 9 | Inheritance | 5–10% |
| 10 | Recursion | 5–7.5% |
Units 5 and 6 carry the highest weight. Units 3, 4, 8, and 9 are also heavily represented. Do not neglect any unit, even those with lower weights, because any topic can appear on the exam.
File Roadmap
This study package contains 27 files organized into the following categories:
Overview (1 file)
00-overview.md— This file. Exam format, reference sheet summary, and file guide.
Unit Notes (10 files)
Each unit note file provides:
- Comprehensive explanations of all tested concepts
- Worked Java code examples with line-by-line analysis
- A list of 5–6 common mistakes students make on the exam
- 6 self-check questions (no answer key — test yourself honestly)
Files:
01-unit1-primitive-types.md01-unit2-using-objects.md01-unit3-boolean-expressions-and-if-statements.md01-unit4-iteration.md01-unit5-writing-classes.md01-unit6-arrays.md01-unit7-arraylist.md01-unit8-2d-arrays.md01-unit9-inheritance.md01-unit10-recursion.md
Unit Practice (10 files)
Each practice file contains:
- 4–5 multiple-choice questions with code-analysis focus
- 1 free-response coding problem modeled after the exam format
Files:
02-practice-unit1.md02-practice-unit2.md02-practice-unit3.md02-practice-unit4.md02-practice-unit5.md02-practice-unit6.md02-practice-unit7.md02-practice-unit8.md02-practice-unit9.md02-practice-unit10.md
Full Practice Exam and Answer Key (2 files)
03-full-practice-exam.md— 40 MCQ + 4 FRQ mirroring the real exam03-full-practice-exam-answers.md— Complete answer key with explanations
Reference and Strategy (3 files)
04-summary-sheet.md— Condensed Java syntax and methods reference05-exam-strategy.md— MCQ code-tracing strategy and FRQ writing strategy06-presentation-outline.md— ~50-slide outline for group review sessions07-audio-script.md— ~15–20 minute audio script for listening review
How to Use This Package
- Start with the unit notes. Read one unit at a time, working through every code example by hand before checking the explanation.
- Complete the self-check questions. Treat them as a pre-test. If you miss more than one, re-read the relevant section.
- Do the unit practice files. Time yourself on the MCQ section (about 2 minutes per question) and the FRQ (about 22 minutes).
- Take the full practice exam. Simulate real conditions: 90 minutes for MCQ, then a break, then 90 minutes for FRQ.
- Review the answer key thoroughly. For every wrong answer, identify which unit the gap belongs to and review that unit note.
- Use the summary sheet and strategy guide in the final days before the exam for quick reference.
- Use the presentation outline and audio script for collaborative or passive review.
Good luck with your preparation. Consistent, focused practice on code tracing and writing is the single most effective way to prepare for AP Computer Science A.
Unit notes
10Unit 1: Primitive Types
Java is a statically typed language, meaning every variable must be declared with a type before it can be used. The AP CSA exam focuses on a subset of Java's primitive types: int, double, boolean, and char. Understanding how these types behave — particularly how arithmetic works, how types interact, and what happens when values exceed their limits — is foundational for every other unit.
The Four Primitive Types on the Exam
int — Integer Values
The int type stores whole numbers (positive, negative, and zero) using 32 bits of memory. The range of an int is approximately –2.147 billion to +2.147 billion (specifically, –2^31 to 2^31 – 1).
int age = 17;
int temperature = -5;
int population = 7500000000; // Compile-time error: value too large for int
If a literal integer value exceeds the int range, the compiler will produce an error. Use long for larger values, though long is not explicitly tested on the AP exam.
double — Floating-Point Values
The double type stores decimal numbers using 64 bits (double precision). It can represent very large and very small numbers, but it stores values in binary, which means some decimal fractions cannot be represented exactly.
double price = 19.99;
double pi = 3.14159265;
double scientific = 6.022e23; // Scientific notation: 6.022 × 10^23
A critical exam concept: double values may have small rounding errors.
double x = 0.1 + 0.2;
// x is 0.30000000000000004, NOT exactly 0.3
This is why you should never compare double values with ==. Instead, check if the absolute difference is within a small tolerance.
boolean — True or False
The boolean type has exactly two possible values: true and false. Boolean variables are used as flags and as the results of relational and logical expressions.
boolean isStudent = true;
boolean hasPassed = false;
boolean isValid = (age >= 0 && age <= 120);
char — Single Characters
The char type stores a single Unicode character using 16 bits. Character literals are enclosed in single quotes.
char letter = 'A';
char digit = '7';
char space = ' ';
Characters are stored as integers internally, so you can perform arithmetic on them. The uppercase letters 'A' through 'Z' correspond to values 65 through 90, and the lowercase letters 'a' through 'z' correspond to values 97 through 122. The digits '0' through '9' correspond to values 48 through 57.
char ch = 'A';
int value = ch; // value is 65
char next = (char)(ch + 1); // next is 'B'
Arithmetic Operators
Java provides five arithmetic operators for numeric types:
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ | Addition | 7 + 3 | 10 |
- | Subtraction | 7 - 3 | 4 |
* | Multiplication | 7 * 3 | 21 |
/ | Division | 7 / 3 | 2 (int) or 2.333... (double) |
% | Modulo (remainder) | 7 % 3 | 1 |
Integer Division
When both operands of the division operator are int, Java performs integer division: the fractional part is discarded (truncated toward zero). It does not round.
int a = 7 / 2; // a is 3 (NOT 3.5, NOT 4)
int b = -7 / 2; // b is -3 (truncation toward zero, NOT -4)
int c = 1 / 3; // c is 0
int d = 3 / 3; // d is 1
The Modulo Operator (%)
The modulo operator returns the remainder of integer division. It is extremely useful on the exam for:
- Checking if a number is even or odd:
n % 2 == 0 - Extracting the last digit of a number:
n % 10 - Cycling through a range of values:
i % nint r1 = 7 % 3; // r1 is 1 int r2 = 10 % 5; // r2 is 0 int r3 = -7 % 3; // r3 is -1 (Java follows dividend sign) int r4 = 7 % -3; // r4 is 1
The sign of the result of
%follows the sign of the dividend (the left operand) in Java.
Mixed-Type Arithmetic
When an int and a double are used together in an expression, Java automatically promotes the int to a double before performing the operation. The result is always a double.
double result1 = 7 / 2; // result1 is 3.0 (int division happens first, then cast to double)
double result2 = 7.0 / 2; // result2 is 3.5 (2 is promoted to 2.0, then division)
double result3 = 7 / 2.0; // result3 is 3.5
The first example above is one of the most common traps on the exam. Even though result1 is declared as double, the division 7 / 2 is performed as integer division first because both operands are integers.
Operator Precedence
When an expression contains multiple operators, Java evaluates them according to precedence rules:
- Parentheses:
()— highest precedence, evaluated left to right - Multiplication, Division, Modulo:
*,/,%— evaluated left to right - Addition, Subtraction:
+,-— evaluated left to rightint x = 3 + 4 2; // x is 11 (4 2 = 8, then 3 + 8) int y = (3 + 4) 2; // y is 14 (3 + 4 = 7, then 7 2) int z = 10 - 3 - 2; // z is 5 (left to right: 10 - 3 = 7, then 7 - 2) int w = 20 % 6 / 2; // w is 1 (20 % 6 = 2, then 2 / 2 = 1)
Type Casting
Casting converts a value from one type to another. There are two forms:
Implicit (Widening) Casting
Java automatically converts a narrower type to a wider type without data loss. This is called widening because the destination type can hold all values of the source type.
`nint → double` (always safe) `nchar → int` (always safe)
int a = 5;
double b = a; // Implicit cast: b is 5.0
Explicit (Narrowing) Casting
Converting from a wider type to a narrower type may lose data, so Java requires an explicit cast.
`ndouble → int` (fractional part is truncated)
double x = 9.99;
int y = (int) x; // y is 9 (truncation, NOT rounding)
int z = (int) (x + 0.5); // z is 10 (manual rounding trick)
When casting a double to an int, the decimal portion is simply discarded. This is truncation, not rounding down. For positive numbers, truncation and floor are the same. For negative numbers, they differ: (int) -3.7 is -3, not -4.
Integer Overflow and Underflow
When an arithmetic operation produces a value outside the range of int, the result wraps around. There is no runtime error or exception.
int max = Integer.MAX_VALUE; // 2147483647
int overflow = max + 1; // -2147483648 (wrapped to MIN_VALUE)
int min = Integer.MIN_VALUE; // -2147483648
int underflow = min - 1; // 2147483647 (wrapped to MAX_VALUE)
The exam tests this concept by asking what happens when you add 1 to Integer.MAX_VALUE or subtract 1 from Integer.MIN_VALUE.
Division by Zero
- Integer division by zero (
int x = 5 / 0;) causes anArithmeticExceptionat runtime. - Double division by zero (
double x = 5.0 / 0;) producesInfinity(positive) or-Infinity(negative). It does not throw an exception. - Double zero divided by zero (
double x = 0.0 / 0.0;) producesNaN(Not a Number).
Assignment Operators and Shorthand
Java provides compound assignment operators that combine an operation with assignment:
int x = 10;
x += 5; // x is now 15 (equivalent to x = x + 5)
x -= 3; // x is now 12
x *= 2; // x is now 24
x /= 4; // x is now 6
x %= 4; // x is now 2
The ++ and -- operators increment and decrement by 1. On the AP exam, these are almost always used as standalone statements. When used in expressions, the prefix form (++x) increments before the value is used, and the postfix form (x++) uses the value first, then increments.
int a = 5;
int b = a++; // b is 5, a is now 6 (postfix: use then increment)
int c = ++a; // a becomes 7, c is 7 (prefix: increment then use)
Worked Example: Tracing a Complex Expression
int a = 17;
int b = 5;
double c = a / b + a % b;
int d = (int)(3.9 + 0.5);
int e = a / (double) b;
Trace:
a / b→17 / 5→3(integer division)a % b→17 % 5→2c→3 + 2→5.0(result promoted to double)(int)(3.9 + 0.5)→(int)(4.4)→4(truncation)a / (double) b→17 / 5.0→3.4(double division)e→(int) 3.4→ Compile error: cannot implicitly convertdoubletoint. You would need(int)(a / (double) b).
Common Mistakes
- Assuming
doubledeclaration fixes integer division.double x = 7 / 2;stores3.0, not3.5. The division happens before the assignment. Fix:double x = 7.0 / 2; - Confusing truncation with rounding.
(int) 3.9is3, not4. Java never rounds automatically when casting. - Using
==to comparedoublevalues. Due to floating-point imprecision,0.1 + 0.2 == 0.3isfalse. Always use a tolerance-based comparison. - Forgetting that
%follows the dividend's sign.-7 % 3is-1, not2.7 % -3is1, not-2. - Assuming integer overflow produces an error. Adding 1 to
Integer.MAX_VALUEsilently wraps toInteger.MIN_VALUE. No exception is thrown. - Using
=instead of==in comparisons.int x = 5; if (x = 3)is a compile error in Java (unlike C/C++), butboolean b = false; if (b = true)compiles and always executes the if block.
Self-Check Questions
- What is the value of
int result = 15 / 4 + 15 % 4;? - What is the value of
double result = 15 / 4 + 15.0 % 4;? - What happens when you evaluate
Integer.MAX_VALUE + 1? - What is the value of
(int)(-2.7)? Explain why. - What is the output of
System.out.println(10 - 3 * 2 + 5 % 3);? - Write an expression that rounds a
doublevaluexto the nearest integer using only casting and basic arithmetic.
Unit 10: Recursion
Recursion is a problem-solving technique where a method calls itself to solve smaller instances of the same problem. Every recursive solution must have a base case (a condition that stops the recursion) and a recursive case (a call that moves closer to the base case). Recursion is tested on the AP exam through code-tracing MCQs and occasionally in FRQs.
Anatomy of a Recursive Method
public static int factorial(int n) {
if (n <= 1) { // Base case
return 1;
} else { // Recursive case
return n * factorial(n - 1);
}
}
Base Case
The base case is the simplest instance of the problem — one that can be solved without recursion. Without a base case (or with an unreachable one), the recursion never stops and eventually causes a StackOverflowError.
Recursive Case
The recursive case breaks the problem into a smaller subproblem and calls the method again with modified arguments. Each recursive call must move closer to the base case.
Tracing Recursion
The key to tracing recursion is to track each method call and its return value using a call stack. Each call is pushed onto the stack; when it returns, it is popped off.
Example: Factorial
factorial(4)
= 4 * factorial(3)
= 4 * 3 * factorial(2)
= 4 * 3 * 2 * factorial(1)
= 4 * 3 * 2 * 1
= 24
Detailed call stack:
factorial(4)→ callsfactorial(3), waitsfactorial(3)→ callsfactorial(2), waitsfactorial(2)→ callsfactorial(1), waitsfactorial(1)→ base case, returns 1factorial(2)→ 2 * 1 = 2, returns 2factorial(3)→ 3 * 2 = 6, returns 6factorial(4)→ 4 * 6 = 24, returns 24
Example: Fibonacci
public static int fib(int n) {
if (n <= 1) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
Tracing fib(4):
fib(4)
= fib(3) + fib(2)
= [fib(2) + fib(1)] + [fib(1) + fib(0)]
= [fib(1) + fib(0) + 1] + [1 + 0]
= [1 + 0 + 1] + 1
= 2 + 1
= 3
The Fibonacci sequence generates a tree of recursive calls. This is highly inefficient (exponential time complexity), but it appears frequently on the exam.
Recursive String Methods
String Reversal
public static String reverse(String s) {
if (s.length() <= 1) {
return s;
}
return reverse(s.substring(1)) + s.charAt(0);
}
Tracing reverse("cat"):
reverse("cat")
= reverse("at") + 'c'
= [reverse("t") + 'a'] + 'c'
= ["t" + 'a'] + 'c'
= "ta" + 'c'
= "tac"
Checking if a String is a Palindrome
public static boolean isPalindrome(String s) {
if (s.length() <= 1) {
return true;
}
if (s.charAt(0) != s.charAt(s.length() - 1)) {
return false;
}
return isPalindrome(s.substring(1, s.length() - 1));
}
Tracing isPalindrome("racecar"):
isPalindrome("racecar") → 'r' == 'r', check isPalindrome("acecar")
isPalindrome("acecar") → 'a' == 'r'? NO → return false
Wait — that's wrong. Let me retrace. "racecar" has length 7. substring(1, 6) gives "aceca".
``nisPalindrome("racecar") → 'r' == 'r', check isPalindrome("acecar")
Hmm, `s.substring(1, s.length() - 1)` where s = "racecar": substring(1, 6) = "aceca". So the trace is:
isPalindrome("racecar") → 'r' == 'r', check isPalindrome("aceca") isPalindrome("aceca") → 'a' == 'a', check isPalindrome("cec") isPalindrome("cec") → 'c' == 'c', check isPalindrome("e") isPalindrome("e") → length 1, return true
Result: true. "racecar" is a palindrome.
## Recursive Array Processing
### Recursive Binary Search
```java
public static int binarySearch(int[] arr, int target, int low, int high) {
if (low > high) {
return -1; // Base case: not found
}
int mid = (low + high) / 2;
if (arr[mid] == target) {
return mid; // Base case: found
} else if (arr[mid] > target) {
return binarySearch(arr, target, low, mid - 1); // Search left half
} else {
return binarySearch(arr, target, mid + 1, high); // Search right half
}
}
Recursive Sum of Array
public static int sumArray(int[] arr, int index) {
if (index >= arr.length) {
return 0; // Base case: past end of array
}
return arr[index] + sumArray(arr, index + 1); // Recursive case
}
Tracing sumArray({3, 5, 2}, 0):
sumArray({3, 5, 2}, 0)
= 3 + sumArray({3, 5, 2}, 1)
= 3 + 5 + sumArray({3, 5, 2}, 2)
= 3 + 5 + 2 + sumArray({3, 5, 2}, 3)
= 3 + 5 + 2 + 0
= 10
Recursive vs. Iterative
Any recursive solution can be rewritten iteratively using a loop (and vice versa). Trade-offs:
| Aspect | Recursive | Iterative |
|---|---|---|
| Readability | Often clearer for tree/branching problems | Clearer for simple linear problems |
| Memory | Uses call stack (risk of StackOverflowError) | Uses constant extra memory |
| Performance | Function call overhead | Generally faster |
| When to use | Problem naturally divides into subproblems | Simple repetition, performance-critical |
Common Mistakes
- Missing or incorrect base case. Without a proper base case, recursion never terminates. The base case must handle the smallest possible input without making another recursive call.
- Not moving toward the base case. If the recursive call uses the same (or larger) input, the base case is never reached. For example,
factorial(n)callingfactorial(n)instead offactorial(n - 1). - Incorrectly tracing the return value. When tracing, write out each call's return value step by step. Do not try to simplify in your head — write it out.
- Confusing the order of operations in the return statement.
return n + mystery(n - 1)addsnafter the recursive call returns.return mystery(n - 1) + ndoes the same thing (addition is commutative), butreturn mystery(n - 1) + mystery(n - 2)makes two separate calls. - Assuming recursion is always better. Some problems are better solved iteratively. The Fibonacci recursive implementation is exponentially slow, while an iterative version is O(n).
- Forgetting that recursive calls use a stack. Each recursive call creates a new set of local variables on the call stack. Deep recursion can exhaust the stack, causing a
StackOverflowError.
Self-Check Questions
- What is the result of
factorial(0)using the method defined in this unit? - Trace
fib(5)and determine the result. - What is the output of
reverse("dog")using the recursive method in this unit? - Write a recursive method
int countEven(int[] arr, int index)that returns the number of even values inarrstarting fromindex. - What happens if a recursive method has no base case?
- Trace
mystery(4)for the following method:```java public static int mystery(int n) { if (n == 0) return 0; if (n == 1) return 1; return mystery(n - 1) + mystery(n - 2); } ```
Unit 2: Using Objects
In Unit 1, you worked with primitive types that store single values directly. In Unit 2, you learn to use objects — variables that reference data structures stored elsewhere in memory. Objects are instances of classes, which serve as blueprints defining what data an object holds and what behaviors it supports. On the AP exam, the most important classes are String, Math, and the wrapper classes Integer and Double.
Creating Objects
Objects are created using the new keyword with a constructor call. A constructor initializes the object's data.
String name = new String("Alice"); // Full form (rarely used for String)
String greeting = "Hello"; // String literal (preferred, auto-created object)
For most classes other than String, you must use new:
Scanner sc = new Scanner(System.in);
An object reference variable does not store the object itself. It stores the memory address where the object lives. This distinction matters when comparing objects and understanding null.
The null Reference
A reference variable that does not point to any object holds the value null. Calling a method on a null reference causes a NullPointerException at runtime.
String word = null;
int len = word.length(); // NullPointerException at runtime
You can check for null before calling methods:
if (word != null) {
int len = word.length(); // Safe
}
String Class
String is the most frequently tested class on the AP exam. Strings are immutable — once created, their contents cannot change. Every method that appears to modify a string actually returns a new String object.
String Constructors and Literals
String s1 = "Hello"; // String literal
String s2 = new String("Hello"); // Explicit construction
// s1 and s2 have the same characters but are different objects
Key String Methods
The AP Java Quick Reference lists several String methods. Know each one's behavior precisely.
int length() — Returns the number of characters in the string.
String s = "apple";
int n = s.length(); // n is 5
String substring(int start) — Returns the substring from index start to the end of the string.
String s = "hello";
String sub = s.substring(2); // sub is "llo"
String substring(int start, int end) — Returns the substring from index start up to but not including index end. The length of the result is end - start.
String s = "hello";
String sub = s.substring(1, 4); // sub is "ell"
// Starts at index 1, ends at index 3 (not including 4)
// Length = 4 - 1 = 3
int compareTo(String other) — Compares two strings lexicographically (dictionary order). Returns:
- A negative integer if
thiscomes beforeother - Zero if they are equal
- A positive integer if
thiscomes afterotherString a = "apple"; String b = "banana"; String c = "apple";
a.compareTo(b); // negative ("apple" < "banana") a.compareTo(c); // 0 (equal) b.compareTo(a); // positive ("banana" > "apple")
compareTocompares character by character using Unicode values. Uppercase letters come before lowercase:'A'is 65,'a'is 97. So"Zebra".compareTo("apple")returns a negative number.boolean equals(String other)— Returnstrueif the strings have the same characters in the same order.String s1 = "Hello"; String s2 = new String("Hello");
s1.equals(s2); // true (same characters) s1 == s2; // false (different objects — do not use == for Strings!)
int indexOf(String str)— Returns the starting index of the first occurrence ofstr, or-1if not found.String s = "Mississippi"; s.indexOf("iss"); // 1 s.indexOf("sip"); // 6 s.indexOf("xyz"); // -1 s.indexOf("is", 3); // 4 (start searching from index 3)
String Immutability
Because Strings are immutable, method calls do not modify the original string:
String s = "hello";
s.toUpperCase(); // Returns "HELLO" but s is still "hello"
s = s.toUpperCase(); // Now s is "HELLO" (reassigned)
String Concatenation
The + operator concatenates strings. When one operand is a String, the other is automatically converted to a String.
String name = "Alice";
int age = 17;
String msg = name + " is " + age; // "Alice is 17"
Evaluation is left to right:
System.out.println(1 + 2 + "abc"); // "3abc" (1+2=3, then + "abc")
System.out.println("abc" + 1 + 2); // "abc12" ("abc"+1="abc1", then +2)
System.out.println(1 + "abc" + 2); // "1abc2"
Math Class
The Math class provides static methods for mathematical operations. You call them using Math.methodName() — you do not create a Math object.
Key Math Methods
static int abs(int x) / static double abs(double x) — Returns the absolute value.
Math.abs(-5); // 5
Math.abs(-3.2); // 3.2
static double pow(double base, double exponent) — Returns base raised to exponent. Always returns a double.
Math.pow(2, 3); // 8.0
Math.pow(4, 0.5); // 2.0 (square root)
static double sqrt(double x) — Returns the square root. Returns NaN if x is negative.
Math.sqrt(25); // 5.0
Math.sqrt(2); // 1.4142135623730951
static double random() — Returns a double in the range [0.0, 1.0) — including 0.0 but excluding 1.0.
// Random integer from 0 to n-1 (n possible values)
int die = (int)(Math.random() * 6); // 0, 1, 2, 3, 4, or 5
// Random integer from 1 to 6
int die2 = (int)(Math.random() * 6) + 1;
// Random integer from min to max (inclusive)
int val = (int)(Math.random() * (max - min + 1)) + min;
static int min(int a, int b) / static double min(double a, double b) — Returns the smaller value.
static int max(int a, int b) / static double max(double a, double b) — Returns the larger value.
Math.min(3, 7); // 3
Math.max(-1, -5); // -1
Wrapper Classes
Wrapper classes allow primitive values to be treated as objects. The AP exam tests two: Integer and Double.
Integer num = new Integer(42); // Creates an Integer object (old style)
Double val = new Double(3.14); // Creates a Double object
Useful Methods
Integer.parseInt(String s)— Converts a String to anint.Double.parseDouble(String s)— Converts a String to adouble.Integer.MAX_VALUE— The largest possibleintvalue.Integer.MIN_VALUE— The smallest possibleintvalue.int n = Integer.parseInt("123"); // n is 123 double d = Double.parseDouble("3.14"); // d is 3.14
If the String cannot be parsed, a
NumberFormatExceptionis thrown at runtime.
Scanner Class
Scanner reads input from various sources. On the AP exam, Scanner is typically used to read from System.in or from a String.
Scanner sc = new Scanner(System.in);
String input = sc.nextLine(); // Reads an entire line
int num = sc.nextInt(); // Reads the next integer token
Reading from a String:
Scanner sc = new Scanner("apple banana cherry");
String first = sc.next(); // "apple"
String second = sc.next(); // "banana"
Common Mistakes
- Using
==to compare String content.==checks if two references point to the same object, not if the strings have the same characters. Always use.equals(). - Off-by-one errors with
substring.substring(1, 4)returns characters at indices 1, 2, and 3 — not 4. The end index is exclusive. - Forgetting String immutability.
s.toUpperCase()does not changes. You must reassign:s = s.toUpperCase(); - Misremembering
Math.random()range. It returns[0.0, 1.0)— 1.0 is never returned. To get a random int from 1 to n, use(int)(Math.random() * n) + 1. - Confusing
Math.powreturn type.Math.pow(2, 3)returns8.0(adouble), not8(anint). If you need anint, you must cast. - Calling
compareToand misinterpreting the return value. A negative return means the calling string comes first lexicographically, not that it is "less than" in a general numeric sense.
Self-Check Questions
- What is the value of
"hello".substring(1, 3)? - What does
"apple".compareTo("banana")return: a negative number, zero, or a positive number? - Why does
String s = "hi"; s.toUpperCase(); System.out.println(s);printhiinstead ofHI? - Write an expression using
Math.random()that generates a random integer between 50 and 100, inclusive. - What is the value of
Integer.parseInt("42") + 8? - What is the output of
System.out.println(10 + 20 + "" + 30 + 40);?
Unit 3: Boolean Expressions and If Statements
Boolean expressions are the decision-making backbone of every program. They evaluate to either true or false and are used to control which blocks of code execute. This unit covers relational operators, logical operators, and the conditional structures built from them: if, else if, else, and switch statements.
Relational Operators
Relational operators compare two values and return a boolean result:
| Operator | Meaning | Example (x = 5) | Result |
|---|---|---|---|
== | Equal to | x == 5 | true |
!= | Not equal to | x != 3 | true |
< | Less than | x < 10 | true |
> | Greater than | x > 5 | false |
<= | Less than or equal | x <= 5 | true |
>= | Greater than or equal | x >= 6 | false |
Comparing Objects
For objects (including String), use .equals() instead of == to compare content:
String a = "hello";
String b = new String("hello");
System.out.println(a == b); // false (different objects)
System.out.println(a.equals(b)); // true (same content)
Logical Operators
Logical operators combine or modify boolean expressions:
AND (&&)
Returns true only if both operands are true.
boolean result = (x > 0) && (x < 10); // true if x is between 0 and 10
OR (||)
Returns true if at least one operand is true.
boolean weekend = (day == 6) || (day == 7); // true if Saturday or Sunday
NOT (!)
Reverses a boolean value.
boolean notReady = !isReady;
Short-Circuit Evaluation
&& and || use short-circuit evaluation: Java evaluates from left to right and stops as soon as the result is determined.
false && anything→ Java does not evaluateanythingtrue || anything→ Java does not evaluateanythingThis matters when the right side could cause an error:
// Safe: if divisor is 0, the second condition is never evaluated if (divisor != 0 && numerator / divisor > 5) { // ... }
// Dangerous: both conditions are always evaluated if (divisor != 0 & numerator / divisor > 5) { // ... // ArithmeticException when divisor is 0 }
On the AP exam, always use
&&and||(short-circuit), not&and|(non-short-circuit).
Compound Boolean Expressions
Complex conditions are built by combining relational and logical operators. Parentheses make the logic clear and control evaluation order:
// Is year a leap year?
boolean isLeap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
// Is c a letter?
boolean isLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
De Morgan's Laws
De Morgan's Laws provide a way to negate compound boolean expressions:
!(A && B)is equivalent to!A || !B!(A || B)is equivalent to!A && !BTo negate a compound expression, negate each individual condition and flip the operator.
// Original boolean inRange = (x >= 0) && (x <= 100);
// Negated using De Morgan's boolean outOfRange = (x < 0) || (x > 100); // NOT: !(x >= 0) && !(x <= 100)
Worked Example of Negation
// Original: valid if (age >= 13) && (age <= 19) && (hasID)
// Negated (invalid):
// !(age >= 13) || !(age <= 19) || !(hasID)
// Simplified:
// (age < 13) || (age > 19) || !hasID
If Statements
Basic If
if (temperature > 90) {
System.out.println("It's hot!");
}
// Code continues here regardless
If-Else
if (score >= 60) {
System.out.println("Pass");
} else {
System.out.println("Fail");
}
If-Else If-Else
Java evaluates conditions top to bottom and executes the first block whose condition is true. All remaining blocks are skipped, even if their conditions would also be true.
int grade = 85;
if (grade >= 90) {
System.out.println("A");
} else if (grade >= 80) {
System.out.println("B"); // This executes
} else if (grade >= 70) {
System.out.println("C"); // Skipped even though 85 >= 70
} else {
System.out.println("F");
}
Common Pattern: Determining Range
When checking mutually exclusive ranges, the order of conditions matters:
// CORRECT: Check narrower conditions first
if (x > 100) {
// large
} else if (x > 50) {
// medium (x is between 51 and 100)
} else {
// small (x is 50 or below)
}
// WRONG: This won't work as intended
if (x > 50) {
// catches everything > 50, including > 100
} else if (x > 100) {
// NEVER reached
}
Switch Statements
A switch statement is an alternative to if-else if chains when comparing a single variable or expression against specific constant values.
int day = 3;
String dayName;
switch (day) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
default:
dayName = "Unknown";
break;
}
Fall-Through Behavior
Without a break statement, execution falls through to the next case:
int x = 2;
switch (x) {
case 1:
System.out.print("A");
case 2:
System.out.print("B"); // Prints B
case 3:
System.out.print("C"); // Prints C (fall-through!)
}
// Output: BC
On the AP exam, fall-through is almost always a bug. Always include break unless fall-through is intentional.
Switch Limitations
- The switch variable type must be
int,char,String, or an enum (notdouble,boolean,long, orfloat) - Case values must be compile-time constants (literals or
finalvariables) - You cannot use relational operators in cases (no
case x > 5:)
Comparing if-else if vs. switch
Use if-else if when:
- Checking ranges (
x > 0 && x < 100) - Checking floating-point values
- Conditions involve multiple variables
Use
switchwhen: - Comparing a single variable against specific literal values
- The code is cleaner and more readable with discrete cases
Common Mistakes
- Using
=instead of==in boolean expressions.if (x = 5)is a compile error forintbut compiles forboolean:if (flag = true)always executes the block because it is an assignment, not a comparison. - Forgetting that
else ifis mutually exclusive. Once one condition matches, later conditions are never checked. Order your conditions from most specific to most general. - Negating incorrectly. The negation of
(x > 5)is(x <= 5), not(x < 5). Apply De Morgan's Laws correctly for compound expressions. - Missing
breakin switch statements. This causes fall-through, which is usually unintentional. The exam often tests whether you can predict the output whenbreakis missing. - Using
==with Strings.if (name == "Alice")compares references, not content. Useif (name.equals("Alice")). - Overcompounding conditions.
if (a == true)is redundant. Writeif (a)instead. Similarly,if (a == false)should beif (!a).
Self-Check Questions
- What is the value of
!(true && false) || true? - Given
int x = 15, what doesif (x > 10)followed byelse if (x > 5)print? Does the second block execute? - Apply De Morgan's Laws to negate
(score >= 0 && score <= 100 && !extraCredit). - What is printed by the following code?
```java int n = 2; switch (n) { case 1: System.out.print("A"); case 2: System.out.print("B"); case 3: System.out.print("C"); break; default: System.out.print("D"); } ```
- Rewrite
if (x > 0 && x < 100)without using&&(using De Morgan's negation to express the opposite condition). - Why does
if (str == "hello")not reliably check ifstrcontains "hello"?
Unit 4: Iteration
Iteration (looping) allows programs to repeat a block of code multiple times. The AP exam tests three loop types (while, for, and enhanced for), nested loops, and common loop patterns including counting, summing, finding maximum/minimum values, and searching. You must be able to trace loops precisely and identify errors in loop logic.
While Loops
A while loop tests a condition before each iteration. If the condition is false initially, the loop body never executes.
int count = 0;
while (count < 5) {
System.out.print(count + " ");
count++;
}
// Output: 0 1 2 3 4
When to Use a While Loop
- When the number of iterations is not known before the loop starts
- When reading input until a sentinel value is encountered
- When the loop may need to execute zero times
// Reading until sentinel Scanner sc = new Scanner(System.in); int sum = 0; int value = sc.nextInt(); while (value != -1) { sum += value; value = sc.nextInt(); }
For Loops
A for loop combines initialization, condition checking, and update into a single line. It is ideal when the number of iterations is known in advance.
for (int i = 0; i < 5; i++) {
System.out.print(i + " ");
}
// Output: 0 1 2 3 4
For Loop Structure
for (initialization; condition; update) {
// body
}
- Initialization — Executes once before the loop begins
- Condition — Evaluated before each iteration; loop continues while
true - Update — Executes after each iteration of the body
Off-by-One Patterns
Count from 1 to n:
for (int i = 1; i <= n; i++)
Count from 0 to n-1:
for (int i = 0; i < n; i++)
Count from n down to 1:
for (int i = n; i >= 1; i--)
Variable Scope in For Loops
The loop variable declared in the initialization is local to the loop. It cannot be accessed after the loop ends.
for (int i = 0; i < 5; i++) {
// i is accessible here
}
// i is NOT accessible here — compile error
Enhanced For Loop (For-Each)
The enhanced for loop iterates over each element in an array or ArrayList without using an index.
int[] nums = {10, 20, 30, 40};
for (int num : nums) {
System.out.print(num + " ");
}
// Output: 10 20 30 40
Limitations of Enhanced For Loop
- You cannot modify the array or ArrayList structure (no adding, removing, or replacing elements by index)
- You cannot access elements by index (you don't know the current position)
- You can only read elements in forward order, from first to last
- You cannot iterate over only part of the collection
int[] arr = {1, 2, 3, 4}; for (int val : arr) { val = 0; // This changes the local copy, NOT the array } // arr is still {1, 2, 3, 4}
Nested Loops
A loop inside another loop. The inner loop completes all its iterations for each single iteration of the outer loop.
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 4; j++) {
System.out.print("*");
}
System.out.println();
}
// Output:
// ****
// ****
// ****
Nested Loop Tracing
int count = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < i; j++) {
count++;
}
}
// i=0: inner runs 0 times
// i=1: inner runs 1 time (j=0)
// i=2: inner runs 2 times (j=0, j=1)
// count is 3
Loop Patterns
Counting
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] > threshold) {
count++;
}
}
Summing
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
Finding Maximum
int max = arr[0]; // Initialize to first element, NOT 0
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
Why not initialize to 0? If all array values are negative, max would incorrectly remain 0.
Finding Minimum
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
Fence-Post Error (Off-by-One)
The fence-post error occurs when the loop prints or processes one too many or one too few items. Think of building a fence: if you need n sections of fence, you need n+1 posts.
// WRONG: prints an extra comma at the end
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ", ");
}
// Output: 1, 2, 3, 4,
// CORRECT: handle first or last element separately
for (int i = 0; i < arr.length; i++) {
if (i > 0) {
System.out.print(", ");
}
System.out.print(arr[i]);
}
// Output: 1, 2, 3, 4
Infinite Loops
An infinite loop occurs when the loop condition never becomes false. On the AP exam, you may need to identify that a loop will never terminate.
int x = 10;
while (x > 0) {
x++;
}
// x starts at 10 and increases forever — infinite loop
int y = 10;
while (y > 0) {
y--;
}
// y decrements to 0, then condition is false — terminates
The break Statement
The break statement exits the nearest enclosing loop immediately. The AP exam occasionally tests break in loops.
for (int i = 0; i < 100; i++) {
if (i == 7) {
break;
}
System.out.print(i + " ");
}
// Output: 0 1 2 3 4 5 6
Worked Example: Digit Manipulation
int num = 12345;
int sum = 0;
while (num > 0) {
int digit = num % 10; // Extract last digit
sum += digit;
num = num / 10; // Remove last digit
}
// sum is 15 (1 + 2 + 3 + 4 + 5)
Common Mistakes
- Infinite loops caused by forgetting to update the loop variable. If the condition variable never changes, the loop never ends. Always ensure progress toward termination.
- Off-by-one errors in loop boundaries.
i <= arr.lengthcauses anArrayIndexOutOfBoundsExceptionbecause valid indices are0toarr.length - 1. - Initializing max/min to 0 instead of an array element. If all values are negative,
maxstays 0 (incorrect). Always initialize toarr[0]and start the loop at index 1. - Modifying a local copy in an enhanced for loop.
for (int val : arr) { val = 0; }does not changearr. Use an indexed loop:arr[i] = 0;. - Confusing
whileanddo-whilebehavior. The AP exam does not testdo-whileloops, but be aware thatwhilechecks the condition before the first iteration. - Incorrectly tracing nested loops. The inner loop restarts from its initial value each time the outer loop iterates. Create a table to trace both variables simultaneously.
Self-Check Questions
- How many times does the following loop execute?
for (int i = 5; i <= 20; i += 3) - What is the value of
countafter the following code runs?```java int count = 0; for (int i = 0; i < 4; i++) { for (int j = i; j < 4; j++) { count++; } } ```
- Write a loop that prints the digits of a positive integer
nin reverse order (e.g., 1234 prints 4, 3, 2, 1). - What is wrong with this code that attempts to find the maximum value in an array?
```java int max = 0; for (int val : arr) { if (val > max) max = val; } ```
- How many stars does the following code print?
```java for (int i = 0; i < 4; i++) { for (int j = 0; j < i + 1; j++) { System.out.print("*"); } } ```
- Write a loop that counts how many even numbers are in an integer array
nums.
Unit 5: Writing Classes
Object-oriented programming (OOP) organizes code into classes, which serve as blueprints for creating objects. A class bundles together data (instance variables) and behavior (methods). This is one of the most heavily weighted units on the AP exam (10–15%), and the FRQ that tests class writing is a near-certainty.
Class Definitions
A class declaration specifies the class name, instance variables, constructors, and methods.
public class Student {
// Instance variables
private String name;
private int gradeLevel;
private double gpa;
// Constructor
public Student(String n, int gl, double g) {
name = n;
gradeLevel = gl;
gpa = g;
}
// Accessor method
public String getName() {
return name;
}
// Mutator method
public void setGpa(double newGpa) {
gpa = newGpa;
}
// Other method
public boolean isHonors() {
return gpa >= 3.5;
}
public String toString() {
return name + ", Grade " + gradeLevel + ", GPA: " + gpa;
}
}
Instance Variables
Instance variables (also called fields or attributes) store the data for each object. Each object has its own copy of each instance variable.
Declaration Rules
- Declared inside the class but outside any method or constructor
- Usually declared with
privateaccess (encapsulation) - Not initialized with local variable scope rules — they have default values:
0forint,0.0fordouble,falseforboolean, andnullfor object referencespublic class Counter { private int count; // Default value is 0 private String label; // Default value is null }
Constructors
A constructor initializes a newly created object. It has the same name as the class and no return type (not even void).
public Student(String n, int gl) {
name = n;
gradeLevel = gl;
gpa = 0.0; // Default for new students
}
Default Constructor
If you do not write any constructor, Java provides a default constructor with no parameters that sets all instance variables to their default values. However, if you write any constructor, the default constructor is no longer automatically provided.
public class Point {
private int x;
private int y;
public Point(int xVal, int yVal) {
x = xVal;
y = yVal;
}
// No default (no-arg) constructor exists anymore
}
// Point p = new Point(); // Compile error!
Accessor Methods (Getters)
Accessor methods return the value of a private instance variable. They take no parameters and have a return type matching the variable.
public int getGradeLevel() {
return gradeLevel;
}
Naming convention: get + variable name with capital first letter.
Mutator Methods (Setters)
Mutator methods change the value of a private instance variable. They take a parameter of the same type as the variable and have a void return type.
public void setGradeLevel(int gl) {
gradeLevel = gl;
}
public vs. private Access
privatemembers can only be accessed within their own classpublicmembers can be accessed from any classEncapsulation is the practice of making instance variables
privateand providingpublicaccessor and mutator methods. This protects the data from being changed in unexpected ways.public class BankAccount { private double balance; // Cannot be accessed directly from outside
public void deposit(double amount) { if (amount > 0) { // Validation in mutator balance += amount; } } }
The this Keyword
The this keyword refers to the current object. It is used to distinguish between instance variables and parameters when they have the same name.
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x; // this.x is the instance variable; x is the parameter
this.y = y;
}
}
Without this, the parameter would shadow the instance variable:
public Point(int x, int y) {
x = x; // This assigns the parameter to itself — instance variable stays 0!
y = y; // Same problem
}
Static Variables and Methods
The static keyword means the variable or method belongs to the class itself, not to any individual object.
Static Variables
A static variable is shared by all instances of the class. There is only one copy.
public class Student {
private String name;
private static int totalStudents = 0; // Shared across all Student objects
public Student(String n) {
name = n;
totalStudents++; // Increment the shared counter
}
public static int getTotalStudents() {
return totalStudents;
}
}
Static Methods
Static methods belong to the class and do not have access to instance variables (they do not operate on a specific object). You call them using the class name.
Math.sqrt(25); // Static method of Math class
Integer.parseInt("42"); // Static method of Integer class
The toString Method
The toString method returns a String representation of an object. It is called automatically when you print an object or concatenate it with a string.
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "(" + x + ", " + y + ")";
}
}
Point p = new Point(3, 4);
System.out.println(p); // Calls toString automatically: (3, 4)
System.out.println("P: " + p); // (3, 4) concatenated into the string
Worked Example: Complete Class
public class Book {
private String title;
private String author;
private int pages;
public Book(String t, String a, int p) {
title = t;
author = a;
pages = p;
}
public String getTitle() { return title; }
public String getAuthor() { return author; }
public int getPages() { return pages; }
public void setPages(int p) {
if (p > 0) {
pages = p;
}
}
public boolean isLongBook() {
return pages > 300;
}
public String toString() {
return "\"" + title + "\" by " + author + " (" + pages + " pages)";
}
}
Common Mistakes
- Using the constructor parameter name without
this. When parameters and instance variables share a name, the parameter shadows the instance variable. Usethis.variable = parameterto avoid this. - Forgetting the default constructor disappears. Once you define any constructor with parameters, Java no longer provides the no-argument constructor.
new ClassName()will fail. - Making instance variables
public. This breaks encapsulation. Always make instance variablesprivateand provide accessors/mutators. - Writing a return statement in a void method.
voidmethods should not return a value.return;(without a value) is acceptable for early exit. - Trying to access instance variables from a static method. Static methods do not operate on a specific object and cannot reference
thisor instance variables directly. - Forgetting that
toStringis called automatically. When you seeSystem.out.println(obj), know thatobj.toString()is being called. This is frequently tested on MCQ.
Self-Check Questions
- What is the difference between an instance variable and a local variable?
- Write a constructor for a
Circleclass withdouble radiusas its only instance variable. Use thethiskeyword. - Why should instance variables be
private? - What is the output of
System.out.println(new Point(1, 2));if thePointclass does not define atoStringmethod? - What is the difference between a static variable and an instance variable?
- Write a class
Temperaturewith adouble celsiusfield, a constructor, a getter, a setter, and a methodtoFahrenheit()that returns the Fahrenheit equivalent.
Unit 6: Arrays
An array is a fixed-size, ordered collection of elements of the same type. Arrays are fundamental data structures on the AP exam and are tested in MCQ code tracing, in the ArrayList FRQ, and in the 2D Array FRQ. Mastering array traversal, searching, sorting, and manipulation is essential.
Array Declaration and Initialization
Declaration
An array variable declaration specifies the element type followed by empty brackets:
int[] scores;
String[] names;
double[] values;
Creating an Array with new
Use new to allocate the array with a specific size. All elements are initialized to default values:
int[] scores = new int[10]; // 10 zeros
String[] names = new String[5]; // 5 nulls
double[] values = new double[3]; // 3 values of 0.0
boolean[] flags = new boolean[4]; // 4 values of false
Array Literal Initialization
int[] primes = {2, 3, 5, 7, 11};
String[] days = {"Mon", "Tue", "Wed", "Thu", "Fri"};
Important: Array Size Is Fixed
Once created, an array's size cannot change. There is no add or remove method. To "resize," you must create a new array and copy elements.
Array Length
Use the length property (not a method — no parentheses) to get the number of elements:
int[] arr = {10, 20, 30};
int n = arr.length; // n is 3 (NO parentheses)
Accessing Elements
Array indices go from 0 to length - 1. Accessing an index outside this range throws an ArrayIndexOutOfBoundsException.
int[] arr = {10, 20, 30, 40, 50};
arr[0]; // 10
arr[4]; // 50
arr[5]; // ArrayIndexOutOfBoundsException!
arr[-1]; // ArrayIndexOutOfBoundsException!
Traversing an Array
Standard For Loop (with index)
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
Enhanced For Loop (without index)
for (int val : arr) {
System.out.println(val);
}
When to Use Each
- Use the indexed for loop when you need the index (to modify elements, access other arrays at the same position, or print positions)
- Use the enhanced for loop when you only need to read each element
Passing Arrays as Parameters
Arrays are passed by reference. When you pass an array to a method, the method receives a reference to the original array and can modify its elements.
public static void doubleValues(int[] arr) {
for (int i = 0; i < arr.length; i++) {
arr[i] *= 2;
}
}
int[] data = {1, 2, 3};
doubleValues(data);
// data is now {2, 4, 6}
Searching
Linear Search
Checks each element one at a time. Works on any array (sorted or unsorted). Time complexity: O(n).
public static int linearSearch(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i; // Found at index i
}
}
return -1; // Not found
}
Binary Search
Requires the array to be sorted. Repeatedly halves the search space. Time complexity: O(log n).
public static int binarySearch(int[] arr, int target) {
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1; // Not found
}
Tracing binary search on {2, 5, 8, 12, 16, 23, 38} looking for 16:
- low=0, high=6, mid=3, arr[3]=12 < 16 → low=4
- low=4, high=6, mid=5, arr[5]=23 > 16 → high=4
- low=4, high=4, mid=4, arr[4]=16 == 16 → return 4
Sorting
Selection Sort
Repeatedly finds the minimum element from the unsorted portion and places it at the beginning.
public static void selectionSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
After each pass of selection sort on {64, 25, 12, 22, 11}:
- Pass 0:
{11, 25, 12, 22, 64}— placed 11 at index 0 - Pass 1:
{11, 12, 25, 22, 64}— placed 12 at index 1 - Pass 2:
{11, 12, 22, 25, 64}— placed 22 at index 2 - Pass 3:
{11, 12, 22, 25, 64}— 25 already in place
Insertion Sort
Builds the sorted portion one element at a time by inserting each element into its correct position.
public static void insertionSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
After each pass of insertion sort on {64, 25, 12, 22, 11}:
- Pass 1:
{25, 64, 12, 22, 11}— inserted 25 before 64 - Pass 2:
{12, 25, 64, 22, 11}— inserted 12 at the beginning - Pass 3:
{12, 22, 25, 64, 11}— inserted 22 between 12 and 25 - Pass 4:
{11, 12, 22, 25, 64}— inserted 11 at the beginning
Merge Sort
A divide-and-conquer algorithm that recursively splits the array in half, sorts each half, then merges them. Time complexity: O(n log n).
The AP exam may ask you to trace the merge process:
Split: {38, 27, 43, 3} → {38, 27} and {43, 3}
Split: {38, 27} → {38} and {27} → merge → {27, 38}
Split: {43, 3} → {43} and {3} → merge → {3, 43}
Merge: {27, 38} and {3, 43} → {3, 27, 38, 43}
Common Array Manipulations
Reversing an Array
for (int i = 0; i < arr.length / 2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
Shifting Elements
// Shift all elements one position to the right
for (int i = arr.length - 1; i > 0; i--) {
arr[i] = arr[i - 1];
}
arr[0] = newValue; // Insert at the front
Common Mistakes
- Using
arr.length()instead ofarr.length.lengthis a property, not a method. No parentheses. - Accessing index
arr.length. Valid indices are 0 toarr.length - 1.arr[arr.length]causes anArrayIndexOutOfBoundsException. - Confusing array reference behavior. Assigning one array variable to another (
int[] b = a;) does NOT create a copy. Both variables reference the same array. - Modifying the loop variable in an enhanced for loop.
for (int val : arr) { val = 0; }does not modify the array. Use an indexed loop to modify elements. - Applying binary search to an unsorted array. Binary search only works correctly on sorted arrays. On an unsorted array, it may miss the target entirely.
- Off-by-one in sorting loops. Selection sort's outer loop runs to
arr.length - 1(notarr.length), because when all but one element are in place, the last element is automatically correct.
Self-Check Questions
- What are the default values of elements in a newly created
int[]andString[]? - Write code to count how many elements in an
int[]array are equal to the first element. - Trace selection sort through two passes on the array
{30, 10, 20, 40}. - What is the result of passing an array to a method and modifying its elements? Does the original array change?
- Why does binary search require the array to be sorted?
- What is wrong with the following code?
```java int[] arr = {1, 2, 3}; for (int i = 0; i <= arr.length; i++) { System.out.println(arr[i]); } ```
Unit 7: ArrayList
An ArrayList is a resizable, ordered collection from Java's Collections Framework. Unlike arrays, ArrayList can grow and shrink dynamically. The AP exam tests ArrayList<E> where E is a reference type (an object or wrapper class). You cannot create an ArrayList<int> — you must use ArrayList<Integer>.
ArrayList vs. Array
| Feature | Array | ArrayList |
|---|---|---|
| Size | Fixed at creation | Resizable |
| Element type | Primitives and objects | Objects only (use wrappers) |
| Length/size | arr.length (no parens) | list.size() (method call) |
| Add element | Not possible (fixed size) | list.add(obj) |
| Remove element | Not directly | list.remove(index) or list.remove(obj) |
| Access element | arr[i] | list.get(i) |
| Set element | arr[i] = val | list.set(i, obj) |
| Iterate | Indexed or enhanced for | Indexed, enhanced for, or Iterator |
Creating an ArrayList
import java.util.ArrayList;
ArrayList<String> words = new ArrayList<String>();
// Or with diamond operator (Java 7+):
ArrayList<String> words2 = new ArrayList<>();
Key Methods
boolean add(E obj) — Append
Adds obj to the end of the list. Always returns true.
ArrayList<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
// list: ["apple", "banana"]
void add(int index, E obj) — Insert
Inserts obj at the specified index, shifting existing elements to the right.
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("C");
list.add(1, "B");
// list: ["A", "B", "C"]
E remove(int index) — Remove by Index
Removes the element at index and returns it. Elements after index shift left.
ArrayList<String> list = new ArrayList<>();
list.add("A"); list.add("B"); list.add("C");
String removed = list.remove(1); // removed is "B"
// list: ["A", "C"]
E get(int index) — Retrieve
Returns the element at index.
String s = list.get(0); // "A"
E set(int index, E obj) — Replace
Replaces the element at index with obj and returns the old value.
list.set(0, "Z"); // list: ["Z", "C"], returns "A"
int size() — Number of Elements
int n = list.size(); // 2
int indexOf(Object obj) — Find Index
Returns the index of the first occurrence, or -1 if not found.
ArrayList<String> list = new ArrayList<>();
list.add("apple"); list.add("banana"); list.add("apple");
list.indexOf("apple"); // 0
list.indexOf("cherry"); // -1
Autoboxing and Unboxing
Java automatically converts between primitives and their wrapper classes:
- Autoboxing:
int→Integer,double→Double - Unboxing:
Integer→int,Double→doubleArrayList<Integer> nums = new ArrayList<>(); nums.add(5); // Autoboxing: int 5 → Integer 5 int val = nums.get(0); // Unboxing: Integer 5 → int 5
The null Problem
Wrapper objects can be null. Unboxing a null wrapper causes a NullPointerException.
Integer num = null;
int val = num; // NullPointerException at runtime
Traversing and Modifying an ArrayList
Printing all elements
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
Removing elements while iterating
Do not remove elements using an enhanced for loop — it causes a ConcurrentModificationException.
// WRONG — ConcurrentModificationException
for (String s : list) {
if (s.length() < 2) {
list.remove(s);
}
}
// CORRECT — iterate backward
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i).length() < 2) {
list.remove(i);
}
}
Iterating backward avoids skipping elements because removing an element only shifts elements at higher indices.
Inserting elements while iterating forward
// Insert "X" before each element — iterate forward
for (int i = 0; i < list.size(); i++) {
list.add(i, "X");
i++; // Skip the element we just processed
}
Common ArrayList Operations
Finding the maximum
int max = list.get(0);
for (int val : list) {
if (val > max) {
max = val;
}
}
Counting elements matching a condition
int count = 0;
for (String s : list) {
if (s.startsWith("A")) {
count++;
}
}
Removing all even numbers
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i) % 2 == 0) {
list.remove(i);
}
}
Reversing an ArrayList
for (int i = 0; i < list.size() / 2; i++) {
String temp = list.get(i);
list.set(i, list.get(list.size() - 1 - i));
list.set(list.size() - 1 - i, temp);
}
Common Mistakes
- Using
ArrayList<int>instead ofArrayList<Integer>. ArrayLists can only hold objects. Use wrapper classes for primitive types. - Using
arr.lengthsyntax on ArrayList. For arrays, it'sarr.length(no parens). For ArrayList, it'slist.size()(with parens). Mixing these up causes compile errors. - Removing elements during forward iteration. Removing shifts elements left, causing the loop to skip the next element. Iterate backward or use a separate list of indices to remove.
- Using enhanced for loop to modify structure. You cannot add or remove from an ArrayList inside an enhanced for loop. Use an indexed loop.
- Forgetting that
remove(int)removes by index.list.remove(2)removes the element at index 2, not the element with value 2. To remove by value, the element must be an object:list.remove(Integer.valueOf(2))orlist.remove(new Integer(2)). - Accessing an empty ArrayList. Calling
get(0)on an empty ArrayList throws anIndexOutOfBoundsException. Always checksize()> 0 first.
Self-Check Questions
- What is the difference between
list.add(obj)andlist.add(index, obj)? - After
list.add("A"); list.add("B"); list.add(1, "C");, what islist? - Why can't you create an
ArrayList<double>? - What happens if you remove an element from an ArrayList while iterating forward with an indexed for loop? Which element gets skipped?
- Write code to remove all strings shorter than 3 characters from an
ArrayList<String>calledwords. - What is the value of
list.size()afterArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.remove(0);?
Unit 8: 2D Arrays
A two-dimensional array is an array of arrays. It organizes data in a grid of rows and columns, making it ideal for representing tables, matrices, grids, and board games. On the AP exam, 2D arrays always have one dedicated FRQ and appear frequently in MCQ tracing questions.
Declaration and Creation
Fixed-Size Initialization
int[][] grid = new int[3][4]; // 3 rows, 4 columns
Access an element with two indices: grid[row][column].
grid.lengthgives the number of rowsgrid[r].lengthgives the number of columns in row r
Literal Initialization
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Row-Major Order
In Java, 2D arrays are stored in row-major order. The first index selects the row, and the second index selects the column within that row.
grid[0][0] grid[0][1] grid[0][2] grid[0][3]
grid[1][0] grid[1][1] grid[1][2] grid[1][3]
grid[2][0] grid[2][1] grid[2][2] grid[2][3]
Memory is laid out row by row: all of row 0, then all of row 1, then all of row 2.
Traversing a 2D Array
Row-by-Row (Standard)
The outer loop iterates over rows; the inner loop iterates over columns within each row.
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
System.out.print(grid[r][c] + " ");
}
System.out.println();
}
Column-by-Column
Swap the loop order to process column by column:
for (int c = 0; c < grid[0].length; c++) {
for (int r = 0; r < grid.length; r++) {
System.out.print(grid[r][c] + " ");
}
System.out.println();
}
Enhanced For Loop
for (int[] row : grid) {
for (int val : row) {
System.out.print(val + " ");
}
System.out.println();
}
The outer enhanced for loop iterates over each row (which is a 1D array). The inner enhanced for loop iterates over each value in that row. This works well for reading but not for modifying elements.
Ragged Arrays
A ragged (or jagged) array has rows of different lengths. Each row is an independent array object.
int[][] ragged = {
{1, 2},
{3, 4, 5, 6},
{7, 8, 9}
};
// Row 0: length 2
// Row 1: length 4
// Row 2: length 3
When traversing ragged arrays, always use grid[r].length for the inner loop bound, not grid[0].length.
for (int r = 0; r < ragged.length; r++) {
for (int c = 0; c < ragged[r].length; c++) {
System.out.print(ragged[r][c] + " ");
}
System.out.println();
}
2D Array Processing Patterns
Row Sum
for (int r = 0; r < grid.length; r++) {
int rowSum = 0;
for (int c = 0; c < grid[r].length; c++) {
rowSum += grid[r][c];
}
System.out.println("Row " + r + " sum: " + rowSum);
}
Column Sum
for (int c = 0; c < grid[0].length; c++) {
int colSum = 0;
for (int r = 0; r < grid.length; r++) {
colSum += grid[r][c];
}
System.out.println("Column " + c + " sum: " + colSum);
}
Finding the Maximum Value
int max = grid[0][0];
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] > max) {
max = grid[r][c];
}
}
}
Counting Elements Meeting a Condition
int count = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] % 2 == 0) {
count++;
}
}
}
Checking if a Value Exists
boolean found = false;
for (int r = 0; r < grid.length && !found; r++) {
for (int c = 0; c < grid[r].length && !found; c++) {
if (grid[r][c] == target) {
found = true;
}
}
}
Modifying a 2D Array
// Multiply every element by 2
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
grid[r][c] *= 2;
}
}
Transposing a Matrix
Swapping rows and columns:
// Only works for square matrices
for (int r = 0; r < grid.length; r++) {
for (int c = r + 1; c < grid[r].length; c++) {
int temp = grid[r][c];
grid[r][c] = grid[c][r];
grid[c][r] = temp;
}
}
Note: the inner loop starts at c = r + 1 to avoid swapping the diagonal and to prevent swapping each pair twice.
Worked Example: Tracing
int[][] arr = {{3, 1, 4}, {1, 5, 9}, {2, 6, 5}};
int sum = 0;
for (int r = 0; r < arr.length; r++) {
for (int c = 0; c < arr[0].length; c++) {
if (r == c) {
sum += arr[r][c];
}
}
}
The condition r == c selects the main diagonal: arr[0][0]=3, arr[1][1]=5, arr[2][2]=5. Sum = 13.
Common Mistakes
- Swapping row and column indices.
grid[3][5]means row 3, column 5 — not the other way around. Remember: first index = row. - Using
grid[0].lengthfor ragged arrays. If rows have different lengths,grid[0].lengthmay not apply to other rows. Always usegrid[r].length. - Off-by-one in loop bounds. The number of rows is
grid.lengthand the number of columns isgrid[r].length. Do not add or subtract 1 unnecessarily. - Confusing row-major with column-major. The standard nested loop (outer = rows, inner = columns) traverses row by row. If the question asks for column-by-column processing, swap the loops.
- Assuming rectangular for all 2D arrays. Not all 2D arrays are rectangular. Always check each row's length individually if the array could be ragged.
- Incorrect diagonal access. The main diagonal has
r == c. The anti-diagonal hasr + c == n - 1(where n is the number of rows/columns in a square matrix).
Self-Check Questions
- Given
int[][] m = {{2, 4}, {6, 8, 10}, {12}};, what ism[1][2]? - What is
m.lengthfor the array above? What ism[1].length? - Write code to find the sum of all elements in the first column of a rectangular 2D array.
- Write code to count how many elements in a 2D int array are negative.
- What indices are on the main diagonal of a 4×4 array?
- Write code to print a 2D array column by column instead of row by row.
Unit 9: Inheritance
Inheritance is a fundamental object-oriented programming concept that allows a new class to extend an existing class, inheriting its fields and methods. The new class (subclass) can add new features or override existing ones. Inheritance enables code reuse and polymorphism — the ability of a variable to refer to objects of different types at runtime.
Superclass and Subclass
- Superclass (parent/base class): The class being extended
- Subclass (child/derived class): The class that inherits from the superclass
The
extendskeyword establishes the inheritance relationship:public class Animal { private String name;
public Animal(String n) { name = n; }
public String speak() { return "..."; }
public String getName() { return name; } }
public class Dog extends Animal { public Dog(String n) { super(n); // Call superclass constructor }
@Override public String speak() { return "Woof"; } }
public class Cat extends Animal { private boolean isIndoor;
public Cat(String n, boolean indoor) { super(n); isIndoor = indoor; }
@Override public String speak() { return "Meow"; } }
The extends Keyword
extends means "inherits from." A subclass inherits all non-private members of the superclass:
- Inherited:
publicandprotectedinstance variables and methods - Not inherited:
privateinstance variables (accessible only through inherited public methods) - Not inherited: Constructors (subclasses must define their own, optionally calling
super)
The super Keyword
super has two uses:
1. Call the Superclass Constructor
The first line of a subclass constructor must be a call to a superclass constructor using super(...).
public Dog(String n) {
super(n); // Must be the very first statement
}
If you do not explicitly call super(...), Java automatically inserts a call to the superclass's no-argument constructor: super(). If the superclass does not have a no-argument constructor, this causes a compile error.
2. Call a Superclass Method
Use super.method() to call the superclass's version of an overridden method.
@Override
public String speak() {
return super.speak() + " (enhanced)"; // Calls Animal's speak()
}
Method Overriding vs. Overloading
Overriding
A subclass provides a new implementation of a method that already exists in the superclass. The method must have the same signature (same name, same parameter types, same return type).
// In Animal:
public String speak() { return "..."; }
// In Dog (overriding):
@Override
public String speak() { return "Woof"; }
Rules for overriding:
- The method signature must be identical
- The return type must be the same
- The access level must be at least as permissive (cannot make a
publicmethodprivate) - Use
@Overrideannotation (best practice; the compiler verifies the override)
Overloading
Two or more methods in the same class have the same name but different parameter lists. This is unrelated to inheritance.
public class MathUtil {
public int max(int a, int b) { return (a > b) ? a : b; }
public double max(double a, double b) { return (a > b) ? a : b; }
public int max(int a, int b, int c) { return max(max(a, b), c); }
}
Polymorphism
A superclass variable can reference a subclass object. At runtime, Java calls the actual object's version of an overridden method, not the variable's type's version.
Animal a = new Dog("Rex"); // Valid: Dog IS an Animal
System.out.println(a.speak()); // "Woof" — calls Dog's speak()
Animal b = new Cat("Whiskers", true);
System.out.println(b.speak()); // "Meow" — calls Cat's speak()
What Polymorphism Means for the Exam
When a variable's declared type differs from its actual type, method calls are resolved based on the actual type at runtime:
Animal[] animals = {new Dog("Rex"), new Cat("Mittens", false), new Animal("Generic")};
for (Animal a : animals) {
System.out.println(a.speak());
}
// Output: Woof, Meow, ...
Polymorphism Limitations
A superclass variable cannot call methods that only exist in the subclass:
Animal a = new Dog("Rex");
a.speak(); // OK — speak() is defined in Animal
// a.fetch(); // Compile error — Animal doesn't have fetch()
To access subclass-specific methods, you need a cast:
if (a instanceof Dog) {
Dog d = (Dog) a;
d.fetch();
}
Abstract Classes and Methods
An abstract class cannot be instantiated. It serves as a template for subclasses. It may contain abstract methods (methods without a body) that subclasses must implement.
public abstract class Shape {
private String name;
public Shape(String n) {
name = n;
}
public String getName() { return name; }
// Abstract method — no body; subclasses MUST implement
public abstract double area();
public abstract double perimeter();
}
public class Circle extends Shape {
private double radius;
public Circle(double r) {
super("Circle");
radius = r;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
}
Key rules:
- An abstract method has no body (no curly braces); it ends with a semicolon
- Any class with an abstract method must be declared abstract
- A subclass of an abstract class must implement all abstract methods, or it must also be declared abstract
- You cannot create an object of an abstract class:
new Shape("x")is a compile error
Object Class Methods
Every class in Java inherits from Object. Two methods are frequently tested:
toString()
Returns a string representation of the object. The default Object.toString() returns the class name and hash code, which is not useful. Classes typically override this.
equals(Object other)
Compares two objects for equality. The default Object.equals() uses == (reference equality). Classes typically override this to compare content.
public class Point {
private int x;
private int y;
public Point(int x, int y) { this.x = x; this.y = y; }
public boolean equals(Object other) {
if (other instanceof Point) {
Point p = (Point) other;
return this.x == p.x && this.y == p.y;
}
return false;
}
}
Worked Example: Polymorphism Tracing
Animal a1 = new Animal("A");
Animal a2 = new Dog("D");
Animal a3 = new Cat("C", true);
System.out.println(a1.speak()); // "..." (Animal's version)
System.out.println(a2.speak()); // "Woof" (Dog's version — polymorphism)
System.out.println(a3.speak()); // "Meow" (Cat's version — polymorphism)
System.out.println(a1.getName()); // "A"
System.out.println(a2.getName()); // "D" — inherited from Animal
Common Mistakes
- Forgetting to call
super()in a subclass constructor. If the superclass has no no-argument constructor, you must explicitly callsuperwith the correct parameters. - Confusing overriding with overloading. Overriding requires the exact same method signature. Overloading requires a different parameter list. They are independent concepts.
- Assuming the variable's type determines which method runs. With polymorphism, the object's actual type determines which overridden method is called, not the variable's declared type.
- Trying to instantiate an abstract class.
new Shape()is illegal. You must instantiate a concrete subclass. - Forgetting
@Overridechanges behavior. If you write a method in a subclass with the same name but a slightly different parameter list, you are overloading, not overriding. The superclass method still runs through a superclass reference. - Casting without
instanceofcheck. Casting a superclass reference to a subclass type that doesn't match causes aClassCastException. Always check withinstanceoffirst.
Self-Check Questions
- What keyword establishes an inheritance relationship between two classes?
- If a subclass constructor does not explicitly call
super(), what happens? - What is the difference between method overriding and method overloading?
- Given
Animal a = new Dog("Rex");, which version ofspeak()is called whena.speak()executes? - Can you create an instance of an abstract class? Why or why not?
- Why should you use
@Overridewhen overriding a method?
Practice sets
10Practice: Unit 1 — Primitive Types
Question 1
What is printed by the following code segment?
int a = 17;
int b = 5;
double c = a / b;
System.out.println(c);
A) 3.4
B) 3.0
C) 3
D) 3.5
E) 2.0
Question 2
What is the value of result after the following code executes?
int x = 100;
int y = 7;
int result = x % y + x / y;
A) 20
B) 21
C) 22
D) 23
E) 14
Question 3
Which of the following expressions correctly rounds a positive double value d to the nearest integer?
A) (int) d
B) (int)(d + 0.5)
C) (int)(d - 0.5)
D) (int) d + 0.5
E) (int)(d * 1.0)
Question 4
What is the value of Integer.MAX_VALUE + 1?
A) Integer.MAX_VALUE
B) 0
C) Integer.MIN_VALUE
D) A compile-time error occurs
E) An ArithmeticException is thrown
Question 5
What is printed by the following code segment?
int a = 10;
int b = 3;
double c = (double) (a / b);
System.out.println(c);
A) 3.333...
B) 3.0
C) 3
D) 3.33
E) A compile-time error occurs
Free-Response Question
Digit Product
Write a method digitProduct that takes a positive integer n and returns the product of its digits.
Method signature: public static int digitProduct(int n)
Examples:
digitProduct(234)returns24(2 × 3 × 4)digitProduct(105)returns0(1 × 0 × 5)digitProduct(7)returns7Assumptions:
nis a positive integer (n > 0).Complete the method below:
public static int digitProduct(int n) { // Your code here }
Practice: Unit 10 — Recursion
Question 1
What is returned by the method call mystery(4)?
public static int mystery(int n) {
if (n <= 1) return 1;
return n + mystery(n - 2);
}
A) 7
B) 8
C) 10
D) 4
E) A StackOverflowError is thrown
Question 2
What is returned by fib(5) using the following method?
public static int fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
A) 3
B) 5
C) 8
D) 13
E) 2
Question 3
What is returned by recur("hello")?
public static String recur(String s) {
if (s.length() <= 1) return s;
return recur(s.substring(1)) + s.charAt(0);
}
A) "hello"
B) "olleh"
C) "h"
D) "o"
E) A StringIndexOutOfBoundsException is thrown
Question 4
What is returned by count(5)?
public static int count(int n) {
if (n == 0) return 0;
return 1 + count(n / 2);
}
A) 2
B) 3
C) 4
D) 5
E) 1
Question 5
Consider the following method:
public static int compute(int n) {
if (n == 0) return 2;
if (n == 1) return 1;
return compute(n - 1) * compute(n - 2);
}
What is returned by compute(4)?
A) 0
B) 1
C) 2
D) 4
E) 8
Free-Response Question
Recursive Count
Write a recursive method countPositive that takes an int[] arr and an int index, and returns the number of positive integers in the array starting from the given index to the end of the array.
Method signature: public static int countPositive(int[] arr, int index)
Examples:
countPositive({-1, 3, -2, 5, 0}, 0)returns2(3 and 5 are positive)countPositive({-1, -2, -3}, 0)returns0countPositive({10, 20, 30}, 1)returns2(20 and 30)Assumptions:
arris not null.indexis between 0 andarr.lengthinclusive.Complete the method below:
public static int countPositive(int[] arr, int index) { // Your code here }
Practice: Unit 2 — Using Objects
Question 1
What is the value of s after the following code executes?
String s = "Mississippi";
System.out.println(s.indexOf("si", 3));
A) 1
B) 3
C) 4
D) 6
E) -1
Question 2
What is printed by the following code segment?
String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a.equals(c));
A) true true true
B) true false true
C) false false true
D) true false false
E) false true true
Question 3
What is printed by the following code segment?
System.out.println(2 + 3 + "hello" + 4 + 5);
A) 23hello45
B) 5hello45
C) 5hello9
D) 23hello9
E) 5hello4 5
Question 4
Which expression generates a random integer in the range 1 through 20, inclusive?
A) (int)(Math.random() * 20)
B) (int)(Math.random() * 20) + 1
C) (int)(Math.random() * 19) + 1
D) (int)(Math.random() * 21)
E) (int)(Math.random() * 21) + 1
Question 5
What is the value of str after the following code executes?
String str = "competition";
str.substring(0, 5);
str.toUpperCase();
A) "COMPET"
B) "competition"
C) "COMPETITION"
D) "Compet"
E) A compile-time error occurs
Free-Response Question
First and Last Digit
Write a method firstAndLast that takes a String s and returns a new String consisting of the first character and the last character of s concatenated together. If s has fewer than 2 characters, return the original string.
Method signature: public static String firstAndLast(String s)
Examples:
firstAndLast("hello")returns"ho"firstAndLast("ab")returns"ab"firstAndLast("z")returns"z"firstAndLast("Java")returns"Ja"Assumptions:
sis not null.Complete the method below:
public static String firstAndLast(String s) { // Your code here }
Practice: Unit 3 — Boolean Expressions and If Statements
Question 1
What is the value of the expression !(a > b) && (c <= d) when a = 3, b = 5, c = 8, d = 8?
A) true
B) false
C) A compile-time error occurs
D) An ArithmeticException is thrown
E) The result cannot be determined
Question 2
What is printed by the following code segment?
int x = 15;
if (x > 20) {
System.out.print("A");
} else if (x > 10) {
System.out.print("B");
} else if (x > 5) {
System.out.print("C");
} else {
System.out.print("D");
}
A) A
B) B
C) BC
D) C
E) D
Question 3
Which of the following is equivalent to !(x > 0 && y > 0) using De Morgan's Laws?
A) x < 0 && y < 0
B) x < 0 || y < 0
C) x <= 0 && y <= 0
D) x <= 0 || y <= 0
E) !(x > 0) && !(y > 0)
Question 4
What is printed by the following code segment?
int n = 3;
switch (n) {
case 1:
System.out.print("ONE");
break;
case 2:
System.out.print("TWO");
case 3:
System.out.print("THREE");
case 4:
System.out.print("FOUR");
break;
default:
System.out.print("OTHER");
}
A) THREE
B) THREE FOUR
C) THREE FOUR OTHER
D) FOUR
E) THREE FOUR OTHER with break in case 2 preventing TWO from printing
Question 5
Consider the following code segment:
boolean a = true;
boolean b = false;
boolean c = true;
boolean result = !((a && b) || (!b && c));
What is the value of result?
A) true
B) false
C) A compile-time error occurs
D) null
E) The result depends on short-circuit evaluation
Free-Response Question
Grade Classification
Write a method classifyGrade that takes an integer score (0–100) and returns a String representing the letter grade according to the following rules:
- 90–100: return
"A" - 80–89: return
"B" - 70–79: return
"C" - 60–69: return
"D" - Below 60: return
"F"If the score is outside the range 0–100, return
"Invalid".Method signature:
public static String classifyGrade(int score)Complete the method below:
public static String classifyGrade(int score) { // Your code here }
Practice: Unit 4 — Iteration
Question 1
What is the value of sum after the following code executes?
int sum = 0;
for (int i = 1; i <= 10; i = i + 2) {
sum += i;
}
A) 20
B) 25
C) 30
D) 55
E) 36
Question 2
What is printed by the following code segment?
int x = 1;
while (x < 100) {
x = x * 2;
}
System.out.println(x);
A) 50
B) 64
C) 100
D) 128
E) 99
Question 3
How many times does System.out.print("*") execute?
for (int i = 0; i < 4; i++) {
for (int j = i; j < 4; j++) {
System.out.print("*");
}
}
A) 10
B) 16
C) 12
D) 14
E) 8
Question 4
What is printed by the following code segment?
int[] arr = {3, 7, 2, 9, 5};
int max = arr[0];
for (int val : arr) {
if (val > max) {
max = val;
}
}
System.out.println(max);
A) 3
B) 7
C) 9
D) 5
E) An ArrayIndexOutOfBoundsException is thrown
Question 5
What is the value of count after the following code executes?
int count = 0;
for (int i = 10; i > 0; i -= 3) {
count++;
}
A) 3
B) 4
C) 5
D) 2
E) 10
Free-Response Question
Remove All Occurrences
Write a method removeAll that takes an int[] arr and an int target, and returns a new int[] containing all elements of arr that are not equal to target. The order of the remaining elements must be preserved.
Method signature: public static int[] removeAll(int[] arr, int target)
Examples:
removeAll({1, 2, 3, 2, 4, 2}, 2)returns{1, 3, 4}removeAll({5, 5, 5}, 5)returns an empty array{}removeAll({1, 2, 3}, 4)returns{1, 2, 3}Assumptions:
arris not null.Complete the method below:
public static int[] removeAll(int[] arr, int target) { // Your code here }
Practice: Unit 5 — Writing Classes
Question 1
Consider the following class:
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; }
}
What is returned by new Point(3, 4).getX()?
A) 3
B) 4
C) 0
D) A compile-time error occurs
E) A NullPointerException is thrown
Question 2
Which of the following best describes the purpose of a private access modifier on an instance variable?
A) The variable can only be accessed within its own class.
B) The variable can be accessed from any class in the same package.
C) The variable can be accessed by subclasses only.
D) The variable cannot be accessed or modified by any code.
E) The variable is shared among all instances of the class.
Question 3
What is printed by the following code segment?
public class Counter {
private int count;
private static int total = 0;
public Counter() {
count = 0;
total++;
}
public void increment() { count++; }
public int getCount() { return count; }
public static int getTotal() { return total; }
}
Counter c1 = new Counter();
c1.increment();
c1.increment();
Counter c2 = new Counter();
c2.increment();
System.out.println(c1.getCount() + " " + c2.getCount() + " " + Counter.getTotal());
A) 2 1 2
B) 2 1 3
C) 2 1 1
D) 0 0 2
E) 3 1 3
Question 4
Consider the following class definition:
public class Book {
private String title;
private int pages;
public Book(String t) {
title = t;
pages = 0;
}
public Book(String t, int p) {
title = t;
pages = p;
}
}
Which of the following statements will compile without error?
A) Book b = new Book();
B) Book b = new Book("Java");
C) Book b = new Book(250);
D) Book b = new Book("Java", 250, 2024);
E) Both B and D
Question 5
What is the output of System.out.println(obj) when obj refers to an instance of a class that does not override toString()?
A) The class name and hash code (e.g., ClassName@1a2b3c)
B) null
C) An empty string
D) A compile-time error occurs
E) "Object"
Free-Response Question
Temperature Converter Class
Write a complete class Temperature with the following specifications:
Instance Variables:
private double celsius— temperature in degrees CelsiusConstructor:
public Temperature(double c)— setscelsiustocMethods:
public double getCelsius()— returns the Celsius valuepublic double toFahrenheit()— returns the Fahrenheit equivalent:celsius * 9.0 / 5.0 + 32public double toKelvin()— returns the Kelvin equivalent:celsius + 273.15public boolean isBelowFreezing()— returnstrueif the Celsius temperature is below 0public String toString()— returns a string in the format"X.X°C (Y.Y°F)"where X.X is the Celsius value and Y.Y is the Fahrenheit value, each with one decimal placeComplete the class below:
public class Temperature { // Your code here }
Practice: Unit 6 — Arrays
Question 1
What is the value of arr[3] after the following code executes?
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0; i < arr.length - 1; i++) {
arr[i] = arr[i + 1];
}
A) 1 B) 2 C) 4 D) 5 E) 0
Question 2
Which of the following correctly creates an array of 20 double values, all initialized to 0.0?
A) double[] arr = new double[20];
B) double[] arr = new double(20);
C) double arr[20] = new double[];
D) double[] arr = {20};
E) double[] arr = new double[]{0.0};
Question 3
What is printed by the following code segment?
int[] a = {3, 1, 4, 1, 5};
int[] b = a;
b[2] = 9;
System.out.println(a[2]);
A) 4 B) 9 C) 3 D) 1 E) An ArrayIndexOutOfBoundsException is thrown
Question 4
Consider the following method:
public static int mystery(int[] arr) {
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] > 0 && arr[i] % 2 == 0) {
count++;
}
}
return count;
}
What is returned by mystery({-2, 0, 4, 7, -6, 3, 8})?
A) 2 B) 3 C) 4 D) 5 E) 1
Question 5
After two complete passes of selection sort on the array {20, 10, 30, 5, 15}, what does the array contain?
A) {5, 10, 30, 20, 15}
B) {5, 10, 15, 20, 30}
C) {5, 15, 30, 20, 10}
D) {5, 10, 20, 30, 15}
E) {10, 5, 30, 15, 20}
Free-Response Question
Mode of an Array
Write a method findMode that takes an int[] arr and returns the value that appears most frequently. If there is a tie, return the smallest value. You may assume the array has at least one element.
Method signature: public static int findMode(int[] arr)
Examples:
findMode({1, 2, 2, 3, 3})returns2(both 2 and 3 appear twice; return the smaller)findMode({5, 5, 5, 1, 2})returns5findMode({7})returns7Complete the method below:
public static int findMode(int[] arr) { // Your code here }
Practice: Unit 7 — ArrayList
Question 1
What is printed by the following code segment?
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add(1, "X");
System.out.println(list.get(2));
A) "A"
B) "B"
C) "C"
D) "X"
E) An IndexOutOfBoundsException is thrown
Question 2
Consider the following code segment:
ArrayList<Integer> nums = new ArrayList<>();
nums.add(3);
nums.add(7);
nums.add(2);
nums.add(9);
nums.remove(1);
nums.add(1, 5);
What is the content of nums after execution?
A) {3, 5, 2, 9}
B) {3, 7, 5, 2, 9}
C) {3, 5, 7, 2, 9}
D) {3, 2, 9, 5}
E) {3, 5, 9}
Question 3
Which of the following correctly declares an ArrayList that stores integer values?
A) ArrayList<int> list = new ArrayList<int>();
B) ArrayList<Integer> list = new ArrayList<Integer>();
C) ArrayList<integer> list = new ArrayList<integer>();
D) ArrayList list = new ArrayList<int>();
E) int[] list = new ArrayList<Integer>();
Question 4
What is the value of list.size() after the following code executes?
ArrayList<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.remove("two");
list.remove(0);
A) 0
B) 1
C) 2
D) 3
E) An error occurs because remove("two") is invalid
Question 5
Consider the following code segment:
ArrayList<Integer> list = new ArrayList<>();
list.add(1); list.add(2); list.add(3); list.add(4); list.add(5);
for (int i = 0; i < list.size(); i++) {
if (list.get(i) % 2 == 0) {
list.remove(i);
}
}
System.out.println(list);
What is printed?
A) [1, 3, 5]
B) [1, 2, 3, 4, 5]
C) [1, 3, 4, 5]
D) [2, 4]
E) [1, 3, 5, 4]
Free-Response Question
Merge Sorted ArrayLists
Write a method mergeSorted that takes two ArrayList<Integer> objects, list1 and list2, each sorted in ascending order, and returns a new ArrayList<Integer> containing all elements from both lists in ascending order.
Method signature: public static ArrayList<Integer> mergeSorted(ArrayList<Integer> list1, ArrayList<Integer> list2)
Examples:
mergeSorted({1, 3, 5}, {2, 4, 6})returns{1, 2, 3, 4, 5, 6}mergeSorted({1, 2}, {3, 4, 5})returns{1, 2, 3, 4, 5}mergeSorted({}, {1})returns{1}Assumptions: Both lists are sorted in ascending order. Either or both lists may be empty.
Complete the method below:
public static ArrayList<Integer> mergeSorted(ArrayList<Integer> list1, ArrayList<Integer> list2) { // Your code here }
Practice: Unit 8 — 2D Arrays
Question 1
Consider the following 2D array:
int[][] grid = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
What is the value of grid[2][1]?
A) 1 B) 4 C) 6 D) 8 E) 9
Question 2
What is printed by the following code segment?
int[][] mat = {{2, 4, 6}, {1, 3, 5}, {0, 8, 7}};
int sum = 0;
for (int r = 0; r < mat.length; r++) {
sum += mat[r][r];
}
System.out.println(sum);
A) 12
B) 15
C) 18
D) 9 E) 6
Question 3
What is the value of count after the following code executes?
int[][] arr = {{1, 0, 2}, {0, 3, 0}, {4, 0, 5}};
int count = 0;
for (int r = 0; r < arr.length; r++) {
for (int c = 0; c < arr[r].length; c++) {
if (arr[r][c] == 0) {
count++;
}
}
}
A) 3 B) 4 C) 5 D) 6 E) 2
Question 4
Which of the following code segments correctly computes the sum of all elements in the first column of a rectangular 2D array grid?
A)
int sum = 0;
for (int r = 0; r < grid.length; r++) {
sum += grid[r][0];
}
B)
int sum = 0;
for (int c = 0; c < grid[0].length; c++) {
sum += grid[0][c];
}
C)
int sum = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
sum += grid[c][r];
}
}
D)
int sum = 0;
for (int r = 0; r < grid[0].length; r++) {
sum += grid[r][0];
}
E) Both A and B
Question 5
Consider the following code segment:
int[][] grid = {{3, 5, 1}, {2, 8, 4}, {7, 0, 6}};
int max = grid[0][0];
int row = 0, col = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] > max) {
max = grid[r][c];
row = r;
col = c;
}
}
}
System.out.println(row + " " + col);
What is printed?
A) 0 1
B) 1 1
C) 2 0
D) 2 2
E) 0 2
Free-Response Question
Replace Negative Values
A 2D array matrix contains integer values. Write a method replaceNegatives that replaces every negative value in the matrix with 0.
Method signature: public static void replaceNegatives(int[][] matrix)
Example: Given matrix = {{3, -1, 4}, {-5, 0, -2}, {7, -3, 8}}, after calling replaceNegatives(matrix), the matrix becomes {{3, 0, 4}, {0, 0, 0}, {7, 0, 8}}.
Assumptions: matrix is not null and is rectangular.
Complete the method below:
public static void replaceNegatives(int[][] matrix) {
// Your code here
}
Practice: Unit 9 — Inheritance
Question 1
Consider the following classes:
public class Vehicle {
private String type;
public Vehicle(String t) { type = t; }
public String getType() { return type; }
public String describe() { return "A " + type; }
}
public class Car extends Vehicle {
private int doors;
public Car(int d) {
super("car");
doors = d;
}
public String describe() { return "A car with " + doors + " doors"; }
}
What is printed by System.out.println(new Car(4).describe());?
A) A car
B) A car with 4 doors
C) A 4
D) A compile-time error occurs
E) A NullPointerException is thrown
Question 2
Consider the following code segment using the classes from Question 1:
Vehicle v = new Car(2);
System.out.println(v.getType());
System.out.println(v.describe());
What is printed?
A) A car and then A car
B) car and then A car
C) car and then A car with 2 doors
D) A car and then A car with 2 doors
E) A compile-time error occurs because v.describe() calls Vehicle's version
Question 3
Which of the following statements about abstract classes is true?
A) An abstract class can be instantiated using new.
B) An abstract class must contain at least one abstract method.
C) A subclass of an abstract class must implement all abstract methods or be declared abstract.
D) Abstract methods can have a body (implementation).
E) A class can extend multiple abstract classes simultaneously.
Question 4
Consider the following classes:
public class Shape {
public double area() { return 0; }
public String toString() { return "shape"; }
}
public class Rectangle extends Shape {
private double w, h;
public Rectangle(double w, double h) { this.w = w; this.h = h; }
public double area() { return w * h; }
public String toString() { return "rectangle"; }
}
What is printed by the following code?
Shape s = new Rectangle(3, 4);
System.out.println(s.area());
System.out.println(s.toString());
A) 0 and then shape
B) 0 and then rectangle
C) 12.0 and then shape
D) 12.0 and then rectangle
E) A compile-time error occurs
Question 5
What is the purpose of the @Override annotation?
A) It allows a method to access private members of the superclass.
B) It causes the compiler to verify that the method actually overrides a method in the superclass.
C) It prevents the method from being overridden in a subclass.
D) It makes the method static.
E) It allows the method to have a different return type than the superclass method.
Free-Response Question
Shape Hierarchy
Consider the following abstract class:
public abstract class Shape {
private String name;
public Shape(String n) { name = n; }
public String getName() { return name; }
public abstract double area();
public abstract double perimeter();
}
Write a class RightTriangle that extends Shape. A RightTriangle has two legs, a and b.
Specifications:
- Constructor:
public RightTriangle(double a, double b)— passes "right triangle" to the superclass constructor and sets the leg lengths area()returnsa * b / 2.0perimeter()returnsa + b + Math.sqrt(a a + b b)Complete the class below:
public class RightTriangle extends Shape { // Your code here }
Summary & cheat sheets
1AP Computer Science A — Quick Reference Summary Sheet
| Type | Size | Range | Default |
|---|---|---|---|
int | 32 bits | ±2.147 billion | 0 |
double | 64 bits | ±1.8 × 10^308 | 0.0 |
boolean | 1 bit | true/false | false |
char | 16 bits | Unicode 0–65535 | '\u0000' |
Arithmetic
int / int→ integer division (truncates, does NOT round)int / doubleordouble / int→ double division%returns remainder; sign follows the dividend- Precedence:
()>* / %>+ -(left to right within same level) - Cast:
(int) 3.9→3(truncation);(double) 5→5.0
Relational & Logical Operators
== != < > <= >=returnboolean&&(AND): both must be true; short-circuits||(OR): at least one true; short-circuits!(NOT): reverses boolean- De Morgan's:
!(A && B)≡!A || !B;!(A || B)≡!A && !B
String Methods
| Method | Returns | Example |
|---|---|---|
length() | int | "hello".length() → 5 |
substring(int start) | String | "hello".substring(2) → "llo" |
substring(int start, int end) | String | "hello".substring(1,4) → "ell" |
compareTo(String other) | int | neg/0/pos |
equals(Object other) | boolean | content comparison |
indexOf(String str) | int | first occurrence index, or -1 |
charAt(int index) | char | character at index |
toUpperCase() | String | new uppercase String |
- Strings are immutable — methods return NEW strings
- String concatenation:
+with at least one String operand; left to right evaluation
Math Class (all static)
| Method | Example | Result |
|---|---|---|
abs(int/double x) | Math.abs(-5) | 5 |
pow(double base, double exp) | Math.pow(2,3) | 8.0 |
sqrt(double x) | Math.sqrt(25) | 5.0 |
random() | Math.random() | [0.0, 1.0) |
min(a, b) | Math.min(3,7) | 3 |
max(a, b) | Math.max(3,7) | 7 |
Random int from min to max inclusive: (int)(Math.random() * (max - min + 1)) + min
Wrapper Classes
Integer.parseInt(String)→intDouble.parseDouble(String)→doubleInteger.MAX_VALUE= 2147483647Integer.MIN_VALUE= -2147483648
Loops
While
while (condition) { body }
For
for (init; condition; update) { body }
Enhanced For (read-only)
for (Type var : collection) { body }
Arrays
- Declaration:
int[] arr = new int[n];orint[] arr = {1, 2, 3}; - Length:
arr.length(no parentheses!) - Indices:
0toarr.length - 1 - Default values: 0 (int), 0.0 (double), false (boolean), null (objects)
- Passed by reference — methods can modify original array
- Cannot resize after creation
Sorting Algorithms
Selection Sort
- Find minimum in unsorted portion, swap to front
- O(n²) comparisons, O(n) swaps
Insertion Sort
- Insert each element into its correct position in the sorted portion
- O(n²) comparisons and swaps
Merge Sort
- Divide in half, sort each half, merge
- O(n log n)
ArrayList<E>
- Must use wrapper types:
ArrayList<Integer>, notArrayList<int> - Size:
list.size()(method call with parentheses!)| Method | Description | |--------|-------------| |
add(E obj)| Appends to end | |add(int index, E obj)| Inserts at index, shifts right | |remove(int index)| Removes at index, shifts left, returns element | |get(int index)| Returns element at index | |set(int index, E obj)| Replaces element, returns old value | |size()| Returns number of elements | |indexOf(Object obj)| Returns first index or -1 |Removing while iterating → iterate backward to avoid skipping.
2D Arrays
int[][] grid = new int[rows][cols];grid.length= number of rowsgrid[r].length= number of columns in row r- Row-major: outer loop = rows, inner loop = columns
- Main diagonal:
r == c - Anti-diagonal:
r + c == n - 1
Classes
public class ClassName {
private Type field; // instance variable
private static Type shared; // class variable (one copy)
public ClassName(Type param) { // constructor (no return type)
this.field = param; // this distinguishes field from param
}
public Type getField() { return field; } // accessor
public void setField(Type v) { field = v; } // mutator
public String toString() { return "..."; } // auto-called by print
}
private= accessible only within classpublic= accessible from anywherestatic= belongs to class, not instancethis= reference to current object- Default constructor disappears when any constructor is defined
Inheritance
class Sub extends Super { }super(args)— call superclass constructor (must be first line)super.method()— call superclass method- Overriding: same signature in subclass (polymorphism applies)
- Overloading: same name, different parameters (same class or across hierarchy)
- Polymorphism:
SuperClass var = new SubClass();— actual type determines method - Abstract class: cannot instantiate; may have abstract methods (no body)
- Abstract method:
public abstract returnType name(params);— subclasses must implement @Override— compiler checks that method actually overrides
Recursion
public static returnType method(params) {
if (base case) { return base value; } // MUST have base case
return recursive call with smaller input; // MUST move toward base
}
Key patterns:
- Factorial:
return n * fact(n - 1); - Fibonacci:
return fib(n-1) + fib(n-2); - String reversal:
return reverse(s.substring(1)) + s.charAt(0); - Recursive search: pass index parameters, shrink the search space
Tracing: write each call on a stack, compute return values bottom-up.
Common Gotchas (Exam Traps)
double x = 7 / 2;→xis3.0, NOT3.5arr.lengthvslist.size()— parentheses difference==for objects checks reference, not content; use.equals()- Strings are immutable —
s.toUpperCase()does not changes - Enhanced for loop cannot modify array/ArrayList elements
- Forward removal from ArrayList skips elements
thisrequired when parameter names match field names- Abstract classes cannot be instantiated with
new - Polymorphism: actual object type determines method, not variable type
(int)(-3.7)→-3(truncation toward zero, not floor)
Exam strategy
1AP Computer Science A — Exam Strategy Guide
Time Management
You have approximately 2 minutes and 15 seconds per question. Not all questions require the same amount of time. Code-tracing questions take longer than conceptual questions. Use this to your advantage:
- Easy conceptual questions: 30–60 seconds — answer and move on
- Medium code tracing: 1.5–2 minutes — trace carefully
- Hard multi-step tracing: 2–3 minutes — use your full budget
- Skip and return: If a question is taking more than 3 minutes, mark it and move on
Code Tracing Strategy: The 5-Step Method
When you encounter a code snippet to trace, follow these steps systematically:
Step 1: Identify the starting state. List all variables and their initial values. For arrays and ArrayLists, write out the full contents.
Step 2: Identify the control structure. Is it a loop? A conditional? A method call? Determine the flow of execution before tracing values.
Step 3: Create a trace table. For each iteration or statement, record the values of every relevant variable. Use a column for each variable and a row for each step.
Example trace table for a loop:
i | arr[i] | sum | condition
-----|--------|--------|-----------
0 | 3 | 3 | 0 < 5 true
1 | 7 | 10 | 1 < 5 true
2 | 2 | 12 | 2 < 5 true
3 | 9 | 21 | 3 < 5 true
4 | 5 | 26 | 4 < 5 true
5 | — | 26 | 5 < 5 false
Step 4: Check for traps. Before finalizing your answer, verify:
- Is it integer division or double division?
- Are array indices within bounds?
- Is String immutability respected?
- Does
==compare references or primitives? - Is short-circuit evaluation relevant?
Step 5: Match to answer choices. Eliminate clearly wrong answers first. If two answers are close, re-trace the specific line where they diverge.
Elimination Strategy for Hard Questions
When you cannot fully trace the code:
- Eliminate answers that would cause compile errors — if the code compiles, these are wrong
- Eliminate answers with wrong data types — if the question asks for an
int, eliminatedoubleanswers - Test boundary values — what happens on the first iteration? The last?
- Look for obvious patterns — is the answer accumulating values (sum), counting, or finding extremes?
- Check the loop bound — off-by-one is the most common error. Does the answer look one iteration too many or too few?
Process of Elimination Technique
Even if you cannot solve a question, never leave it blank. Use these heuristics:
- If exactly one answer is negative and the code involves subtraction or negative inputs, it might be the one
- If the code has
arr.length - 1in the bound and one answer seems to skip the last element, it is likely correct - If the question asks about
toString, look for the answer that matches the format shown in the method
Section II: Free-Response Strategy (4 Questions, 90 Minutes)
Time Management
You have 22.5 minutes per FRQ. Allocate your time as follows:
- FRQ 1 (Methods & Control Structures): 20 minutes
- FRQ 2 (Classes): 25 minutes
- FRQ 3 (Array/ArrayList): 22 minutes
- FRQ 4 (2D Array): 23 minutes
- Buffer: 10 minutes for review
General FRQ Writing Rules
- Do not write import statements. They are provided or not needed.
- Do not write class headers, main methods, or
public static void mainunless asked. - Write only the method or class requested. Do not add extra methods.
- Use the exact method signatures provided. Do not change parameter names or types.
- You may use
//comments to explain your logic. Graders read them and they can earn partial credit. - Do not worry about perfect style. The focus is on correctness of logic.
- Attempt every question. Partial credit is generous. Even pseudocode can earn points.
FRQ 1: Methods and Control Structures
This FRQ asks you to write 2–3 methods involving:
- String manipulation (substring, charAt, indexOf, length)
- Loops with conditionals
- Mathematical computations
- Tracing through data
Strategy:
- Read the entire problem description before writing code
- Identify the input parameters and return type for each method
- Write the simplest logic first, then handle edge cases
- If the problem involves String parsing, use
substringandInteger.parseInt
FRQ 2: Writing a Class
This FRQ asks you to write a complete class with:
- Instance variables
- A constructor
- Accessor and mutator methods
- Additional methods that process the instance data
Strategy:
- Declare instance variables first (usually
private) - Write the constructor, using
thisif parameter names match field names - Write each method one at a time
- Read each method description carefully — note the exact return type and behavior
- Check: does the problem mention validation? (e.g., negative values, bounds checking)
FRQ 3: Array/ArrayList Processing
This FRQ involves traversing and manipulating arrays or ArrayLists:
- Counting, summing, finding max/min
- Removing elements meeting a condition
- Modifying elements in place
- Returning a new array or ArrayList
Strategy:
- Determine if you need an indexed loop or enhanced for loop (use indexed if modifying)
- If removing elements from an ArrayList, iterate backward
- If returning a new array, count matching elements first, create the array, then fill it
- If returning a new ArrayList, create it and add qualifying elements
- Always check for empty arrays/ArrayLists before accessing elements
FRQ 4: 2D Array Processing
This FRQ involves:
- Row-by-row or column-by-column traversal
- Processing rows or columns independently
- Finding patterns in a grid
- Modifying values based on position
Strategy:
- Use
grid.lengthfor the number of rows andgrid[r].lengthfor columns in row r - For row-by-row: outer loop = rows, inner loop = columns
- For column-by-column: outer loop = columns, inner loop = rows
- If the problem mentions "ragged," use
grid[r].lengthnotgrid[0].length - Draw a small example grid and trace your logic before writing code
Partial Credit: How to Maximize Your Score
AP FRQs are scored using detailed rubrics. Points are assigned for specific tasks, not overall correctness. To maximize partial credit:
- Write something for every method. Even if you cannot solve the full problem, a loop that iterates correctly earns points.
- Use meaningful variable names.
count,sum,max,indexsignal your intent to the grader. - Handle edge cases. Checking for empty arrays or invalid inputs often earns a dedicated point.
- Comment your intent. If you cannot write the code, write a comment:
// I need to count elements > threshold here - Do not erase. Cross out mistakes instead of erasing them. Graders can give credit for crossed-out correct code.
- Attempt the hard parts. Even incomplete logic for finding a maximum or processing a 2D array can earn points for correct loop structure or correct comparison logic.
Common FRQ Mistakes to Avoid
- Using
arr.length()instead ofarr.length - Using
list.lengthinstead oflist.size() - Removing from an ArrayList while iterating forward with an indexed for loop
- Returning a value from a
voidmethod - Forgetting
thisin constructors when parameter names match field names - Using
==to compare Strings - Forgetting that
substringend index is exclusive - Declaring variables inside a loop that should be outside (e.g.,
suminside the loop)
Final Week Checklist
- [ ] Complete at least one full timed practice exam
- [ ] Review every unit note, focusing on common mistakes
- [ ] Memorize the summary sheet (4-summary-sheet.md)
- [ ] Practice writing classes from scratch (FRQ 2 format)
- [ ] Practice 2D array traversal patterns (row sums, column sums, finding max)
- [ ] Time yourself on 4 FRQs in 90 minutes
- [ ] Review the Java Quick Reference contents — know what is and is not on it
- [ ] Get adequate sleep the night before the exam
Presentation outline
1AP Computer Science A — Presentation Outline (~50 Slides)
Slide 1: Title Slide
- Title: AP Computer Science A — Complete Review
- Subtitle: Everything You Need for Exam Day
- Presenter name and date
Slide 2: Exam Overview
- Section I: 40 MCQ, 90 minutes, 50%
- Section II: 4 FRQ, 90 minutes, 50%
- No calculator, no penalty for guessing
- Java Quick Reference provided
Slide 3: Unit Weight Distribution
- Visual bar chart showing approximate weights
- Units 5–6: 10–15% each (highest)
- Units 3–4, 8–9: 7.5–10% each
- Units 1–2, 7, 10: 2.5–7.5% each
Slide 4: What's on the Reference Sheet
- String methods: length, substring, compareTo, equals, indexOf
- Math methods: abs, pow, sqrt, random, min, max
- Integer: parseInt, MAX_VALUE, MIN_VALUE
- Double: parseDouble
- ArrayList: add, remove, get, set, size, indexOf
Slide 5: What's NOT on the Reference Sheet
- Loop syntax (for, while, enhanced for)
- Array declaration and initialization
- Scanner methods
- Inheritance syntax (extends, super)
- charAt, toUpperCase, toLowerCase details
- Sorting algorithm implementations
Primitive Types (Slides 6–10)
Slide 6: The Four Primitive Types
int: whole numbers, 32 bits, ±2.147 billiondouble: decimal numbers, 64 bits, IEEE 754boolean: true/falsechar: single Unicode character, 16 bitsSlide 7: Integer Division Trap
7 / 2→3(NOT 3.5)double x = 7 / 2;→xis3.0(NOT 3.5)- Fix:
7.0 / 2or(double) 7 / 2 - Truncation:
(int) 3.9→3,(int) -3.9→-3Slide 8: Modulo Operator
- Returns remainder:
17 % 5→2 - Sign follows dividend:
-7 % 3→-1 - Uses: even/odd check, last digit, cycling
Slide 9: Overflow and Division by Zero
Integer.MAX_VALUE + 1→Integer.MIN_VALUE(wraps, no error)5 / 0→ArithmeticException5.0 / 0→Infinity(no exception)Slide 10: Operator Precedence
- Parentheses >
* / %>+ - - Same precedence: left to right
- Example:
3 + 4 * 2→11, not14
Using Objects (Slides 11–15)
Slide 11: String Immutability
- Strings never change after creation
s.toUpperCase()returns a NEW string;sis unchanged- Must reassign:
s = s.toUpperCase();Slide 12: Key String Methods
length(): number of characterssubstring(start, end): from start to end-1 (end is exclusive!)compareTo: returns negative, zero, or positiveequals: compares content (use instead of==)indexOf: returns first occurrence index or -1Slide 13: String Concatenation
+with a String operand converts the other to String- Left to right:
1 + 2 + "hi"→"3hi" "hi" + 1 + 2→"hi12"Slide 14: Math Class
- All static methods:
Math.methodName() random()returns [0.0, 1.0) — never 1.0powreturns double:Math.pow(2, 3)→8.0- Random int from a to b:
(int)(Math.random() * (b - a + 1)) + aSlide 15: Wrapper Classes & Scanner
Integer.parseInt("42")→int 42ArrayList<Integer>— must use wrapper, not primitive- Autoboxing:
int↔Integer(automatic)
Boolean Expressions & If Statements (Slides 16–19)
Slide 16: Logical Operators & Short-Circuit
&&: both must be true;||: at least one true- Short-circuit:
false && X→ X never evaluated - Protects against errors:
x != 0 && y / x > 5Slide 17: De Morgan's Laws
!(A && B)≡!A || !B!(A || B)≡!A && !B- Negate each condition, flip the operator
Slide 18: If-Else If Chain
- Mutually exclusive: first true condition wins
- Order matters: check specific before general
switch: use for comparing single value against constants- Fall-through without
breakSlide 19: Common Boolean Traps
=vs==(assignment vs comparison)==with Strings (use.equals())if (b = true)compiles for boolean and always executes
Iteration (Slides 20–23)
Slide 20: Loop Types
while: unknown iterations, may execute 0 timesfor: known iterations, combines init/condition/update- Enhanced for: read-only traversal, no index access
Slide 21: Common Loop Patterns
- Counting: increment counter when condition met
- Summing: accumulate into a sum variable
- Max/Min: initialize to
arr[0], compare each element - Fence-post: handle first/last element separately to avoid extra comma
Slide 22: Nested Loops
- Inner loop completes all iterations per outer iteration
- Count iterations: sum of 0+1+2+...+(n-1) = n(n-1)/2 for triangular pattern
- Trace with a table for both variables
Slide 23: Infinite Loops & Common Errors
- Loop variable never reaches termination condition
- Off-by-one:
i <= arr.lengthcauses ArrayIndexOutOfBoundsException - Enhanced for loop cannot modify array elements
Writing Classes (Slides 24–28)
Slide 24: Class Structure
- Instance variables: private, default values for primitives
- Constructor: same name as class, no return type, initializes object
- Accessor (getter): returns field value
- Mutator (setter): changes field value
Slide 25: The
thisKeyword - Refers to the current object
- Distinguishes fields from parameters with same name
this.field = field;— withoutthis, parameter assigns to itselfSlide 26: public vs private vs static
private: only within the class (encapsulation)public: accessible from anywherestatic: belongs to class, shared by all instances- Static methods cannot access instance variables
Slide 27: Default Constructor & toString
- Default (no-arg) constructor exists only if NO constructors are defined
toString(): called automatically byprintand+concatenation- Override it to provide meaningful output
Slide 28: Common Class Mistakes
- Forgetting
thisin constructors - Writing a return value in a void method
- Assuming default constructor exists after defining any constructor
Arrays (Slides 29–33)
Slide 29: Array Basics
- Fixed size after creation
arr.length— no parentheses!- Default values: 0, 0.0, false, null
- Passed by reference: methods can modify original
Slide 30: Array Traversal & Patterns
- Standard for loop (indexed) for modification
- Enhanced for loop for read-only access
- Finding max: initialize to
arr[0], start loop at index 1Slide 31: Searching
- Linear search: O(n), works on unsorted arrays
- Binary search: O(log n), requires sorted array
- Returns index or -1 if not found
Slide 32: Sorting
- Selection sort: find min, swap to front. O(n²)
- Insertion sort: insert into sorted portion. O(n²)
- Merge sort: divide and merge. O(n log n)
Slide 33: Array Traps
arr.lengthvslist.size()arr.length - 1for last valid indexint[] b = a— same array, not a copy- Modifying local copy in enhanced for loop does nothing
ArrayList (Slides 34–37)
Slide 34: ArrayList Basics
- Resizable, objects only (use wrappers for primitives)
ArrayList<Integer>— NOTArrayList<int>list.size()— with parentheses!Slide 35: ArrayList Methods
add(obj): append to endadd(index, obj): insert, shifts rightremove(index): removes by index, shifts leftget(index): retrieveset(index, obj): replaceSlide 36: Modifying ArrayLists Safely
- Removing while iterating: go BACKWARD
- Forward removal skips elements after shift
- Enhanced for loop + remove = ConcurrentModificationException
Slide 37: Autoboxing & null
int↔Integeris automaticInteger n = null; int x = n;→ NullPointerExceptionremove(int)removes by INDEX, not by value
2D Arrays (Slides 38–41)
Slide 38: 2D Array Structure
- Array of arrays:
int[][] grid = new int[rows][cols]; grid.length= number of rowsgrid[r].length= columns in row r- Row-major order: rows first, then columns
Slide 39: 2D Traversal Patterns
- Row-by-row: outer = rows, inner = columns
- Column-by-column: outer = columns, inner = rows
- Diagonal:
r == c(main) orr + c == n - 1(anti)Slide 40: 2D Processing
- Row sum, column sum, total sum
- Finding max/min in entire grid
- Counting elements meeting a condition
Slide 41: Ragged Arrays
- Rows may have different lengths
- Always use
grid[r].length, notgrid[0].length - Enhanced for loop handles this naturally
Inheritance (Slides 42–46)
Slide 42: Inheritance Basics
class Sub extends Super— Sub inherits non-private memberssuper(args)— call superclass constructor (first line only)super.method()— call superclass versionSlide 43: Polymorphism
Animal a = new Dog();— variable type is Animal, object is Dog- Method calls use the ACTUAL object's version
a.speak()calls Dog's speak(), not Animal'sSlide 44: Overriding vs Overloading
- Overriding: same signature in subclass;
@Overrideverifies - Overloading: same name, different parameters (not inheritance-related)
Slide 45: Abstract Classes
- Cannot instantiate with
new - May have abstract methods (no body, end with semicolon)
- Concrete subclasses MUST implement all abstract methods
- Can have constructors (called via
super()by subclasses)Slide 46: Object Class Methods
toString(): default returns class@hashcode; override for useful outputequals(Object): default uses==; override for content comparison
Recursion (Slides 47–50)
Slide 47: Recursion Structure
- Base case: simplest instance, stops recursion
- Recursive case: calls itself with smaller input, moves toward base
- No base case or unreachable base → StackOverflowError
Slide 48: Tracing Recursion
- Write each call on a stack
- Compute return values from the bottom up
- Example: factorial(4) = 4 × 3 × 2 × 1 = 24
Slide 49: Common Recursion Patterns
- Factorial:
return n * fact(n-1); - Fibonacci:
return fib(n-1) + fib(n-2);(tree of calls) - String reversal:
return reverse(substring(1)) + charAt(0); - Array sum:
return arr[i] + sum(arr, i+1);Slide 50: Final Tips & Good Luck
- Answer every MCQ — no penalty for guessing
- Attempt every FRQ part — partial credit is generous
- Trace code with tables, not in your head
- Trust your preparation. Good luck!
Audio script
1AP Computer Science A — Audio Review Script
Welcome to this AP Computer Science A audio review. This script covers the ten core units tested on the exam and highlights the most common pitfalls that students encounter. Whether you are listening during a commute, a walk, or a study break, this review will reinforce the key concepts you need for exam day. Let's get started.
Primitive Types (approximately 2 minutes)
Java has four primitive types on the AP exam: int, double, boolean, and char. The int type stores whole numbers using 32 bits, giving it a range of roughly negative 2.147 billion to positive 2.147 billion. The double type stores decimal numbers with 64 bits of precision.
The single most tested concept with primitives is integer division. When both operands of the division operator are integers, Java performs integer division, which simply truncates the decimal part. So 7 divided by 2 is 3, not 3.5. Here is the critical trap: even if you write "double x equals 7 divided by 2," the division happens first between two integers, producing 3, and then that 3 is promoted to 3.0. To get 3.5, at least one operand must be a double, like 7.0 divided by 2.
The modulo operator returns the remainder of integer division. 17 modulo 5 is 2. On the AP exam, modulo is used to check even or odd, extract the last digit of a number, and cycle through ranges.
Casting a double to an int truncates toward zero. Casting 3.9 gives 3. Casting negative 3.7 gives negative 3, not negative 4. This is truncation, not rounding.
Finally, integer overflow wraps around silently. Adding 1 to Integer.MAX_VALUE gives Integer.MIN_VALUE. There is no error and no exception. This concept appears on nearly every exam.
Using Objects (approximately 2 minutes)
The most important class on the AP exam is String. Strings are immutable, meaning they can never be changed after creation. When you call a method like toUpperCase or substring, it returns a brand new String object. The original remains unchanged. This is a frequent source of mistakes.
Know the key String methods. Length returns the number of characters. Substring with one argument returns from that index to the end. Substring with two arguments returns from the start index up to but not including the end index. The end index is exclusive. CompareTo returns a negative number, zero, or positive number depending on lexicographic order. Equals compares the actual content of two strings. IndexOf returns the starting index of a substring, or negative 1 if not found.
For String comparison, never use the double equals operator. Double equals checks whether two references point to the same object, not whether they contain the same characters. Always use the equals method.
String concatenation with the plus operator evaluates left to right. So 1 plus 2 plus "hello" gives "3hello" because the integer addition happens first. But "hello" plus 1 plus 2 gives "hello12" because the string concatenation happens first.
The Math class provides static methods. Math.random returns a value in the range 0.0 inclusive to 1.0 exclusive. To get a random integer from 1 to n, use the formula: (int)(Math.random() times n) plus 1. Math.pow returns a double, even if the result is a whole number.
Boolean Expressions and If Statements (approximately 1.5 minutes)
Boolean expressions combine relational and logical operators. The logical AND operator, written as two ampersands, requires both sides to be true. The logical OR operator, written as two vertical bars, requires at least one side to be true.
Both AND and OR use short-circuit evaluation. In a false AND expression, the right side is never evaluated. In a true OR expression, the right side is never evaluated. This matters when the right side could cause an error, like division by zero.
De Morgan's Laws are essential for negating compound expressions. The negation of A AND B is NOT A OR NOT B. The negation of A OR B is NOT A AND NOT B. To negate a compound expression, negate each individual condition and flip the operator.
In an if-else if-else chain, only the first true condition executes. Once a condition matches, all remaining branches are skipped, even if their conditions would also be true. Order your conditions from most specific to most general.
Switch statements require break to prevent fall-through. Without break, execution continues into the next case.
Iteration (approximately 2 minutes)
Java has three loop types. While loops check the condition before each iteration and may execute zero times. For loops combine initialization, condition, and update in one line. Enhanced for loops iterate over arrays and ArrayLists without using an index.
The enhanced for loop is read-only. Assigning to the loop variable inside an enhanced for loop changes a local copy, not the original array element. To modify elements, use an indexed for loop.
Common loop patterns include counting, summing, and finding maximum or minimum values. When finding a maximum, initialize the max variable to the first element of the array, not to zero. If all elements are negative, initializing to zero would give an incorrect result.
The fence-post error occurs when a loop prints or processes one too many or one too few items. This commonly appears when printing comma-separated values and an extra comma appears at the end.
For nested loops, the inner loop completes all its iterations for each single iteration of the outer loop. To count total iterations of a triangular nested loop pattern, sum 0 plus 1 plus 2 up to n minus 1, which equals n times n minus 1 divided by 2.
Writing Classes (approximately 1.5 minutes)
Classes bundle data and behavior together. Instance variables should be declared private to enforce encapsulation. Public accessor methods, or getters, return the value of a private field. Public mutator methods, or setters, change the value.
Constructors initialize objects. They have the same name as the class and no return type. If you define any constructor, Java no longer provides the default no-argument constructor.
The this keyword refers to the current object. It is essential inside constructors when parameter names match instance variable names. Without this, the parameter shadows the instance variable, and the field remains at its default value of zero or null.
Static variables are shared by all instances of a class. There is only one copy. Static methods belong to the class and cannot access instance variables directly.
The toString method returns a string representation of an object. It is called automatically when you print an object or concatenate it with a string using the plus operator.
Arrays (approximately 1.5 minutes)
Arrays are fixed-size, ordered collections of elements of the same type. Use arr.length, without parentheses, to get the number of elements. Valid indices are 0 to arr.length minus 1.
Arrays are passed to methods by reference. If a method modifies the elements of an array parameter, the original array is changed. However, assigning a new array to the parameter variable inside the method does not affect the original.
The three sorting algorithms on the exam are selection sort, insertion sort, and merge sort. Selection sort repeatedly finds the minimum and swaps it to the front. Insertion sort builds a sorted portion by inserting each element into its correct position. Merge sort divides the array in half, sorts each half, and merges them back together.
Binary search requires a sorted array and repeatedly halves the search space. It runs in logarithmic time. Linear search checks each element one at a time and works on any array.
ArrayList (approximately 1.5 minutes)
An ArrayList is a resizable collection that can only hold objects. Use wrapper classes for primitives: ArrayList of Integer, not ArrayList of int. The size method, with parentheses, returns the number of elements.
Key methods include: add to append, remove by index to delete and shift, get to retrieve, set to replace, and indexOf to find the first occurrence.
When removing elements while iterating, always iterate backward. Iterating forward and removing causes the loop to skip elements because removal shifts subsequent elements to the left. Never remove elements inside an enhanced for loop, as this causes a ConcurrentModificationException.
The remove method with an int parameter removes by index, not by value. Remove of integer 2 removes the element at index 2, not the element with value 2.
2D Arrays (approximately 1 minute)
A 2D array is an array of arrays. Grid.length gives the number of rows. Grid of r dot length gives the number of columns in row r. For ragged arrays where rows have different lengths, always use the per-row length.
Row-major traversal means the outer loop iterates over rows and the inner loop iterates over columns. Column-major traversal swaps the loop order. The main diagonal elements are those where row index equals column index.
Inheritance (approximately 1.5 minutes)
Inheritance allows a subclass to extend a superclass, inheriting its non-private members. Use the extends keyword. Call the superclass constructor with super, which must be the first line of the subclass constructor.
Polymorphism means that a superclass variable can reference a subclass object. When a method is called, Java uses the actual object's type, not the variable's declared type, to determine which version of an overridden method to run.
Overriding means a subclass provides a new implementation of a superclass method with the exact same signature. Overloading means two methods in the same class have the same name but different parameter lists. These are independent concepts.
Abstract classes cannot be instantiated. They may contain abstract methods with no body. A concrete subclass must implement all inherited abstract methods or itself be declared abstract.
Recursion (approximately 1.5 minutes)
Every recursive method needs a base case that stops the recursion and a recursive case that calls the method with a smaller input, moving toward the base case. Without a reachable base case, recursion continues indefinitely and causes a StackOverflowError.
To trace recursion, write each method call as a separate line, indenting to show the call depth. Compute return values from the bottom of the call stack upward.
Common recursive patterns include factorial, where the return is n times factorial of n minus 1; Fibonacci, which makes two recursive calls; string reversal, which processes the substring and appends the first character; and recursive array sum, which adds the current element to the recursive call for the rest of the array.
Final Reminders (approximately 30 seconds)
Before you go, remember these final tips. First, answer every multiple-choice question. There is no penalty for guessing. Second, attempt every part of every free-response question. Partial credit is generous, and even incomplete code can earn points. Third, on the free-response section, you do not need to write import statements or a main method. Write only the methods or classes requested. Fourth, trace code systematically using tables rather than trying to do it all in your head. Finally, trust your preparation. You have practiced the patterns, traced the code, and written the methods. Good luck on the exam.