AP Computer Science A — Using Objects and Methods (Deep Study Notes)
Objects, Classes, and the Java API
What an object is (and why Java cares so much)
An object is a bundled package of data and behavior. The data an object “remembers” is called its state (for example, the characters inside a String, or the current position inside a Scanner as it reads input). The behavior an object can perform is expressed through methods (for example, length() for a String, or nextInt() for a Scanner).
Java is an object-oriented language, which means that most useful work is done by creating objects and asking them to do things by calling methods. This matters because AP Computer Science A questions often give you code using objects you didn’t write (from the Java library) and expect you to predict what it does or write a few lines that use those objects correctly.
A helpful analogy: a class is like a blueprint for a type of device, and an object is an actual device built from that blueprint. Two phones can be the same model (same class) but have different battery levels and open apps (different state).
Classes: the “type” of an object
A class defines what state and methods objects of that class will have. When you declare a variable of a class type, you are saying, “This variable can refer to an object built from this class.”
For example, String is a class in the Java standard library. Any particular piece of text (like "hello") is a String object.
The Java API and why you should treat it like a menu
The Java API (Application Programming Interface) is the collection of prewritten classes and methods Java provides. In AP CSA, you’re expected to use parts of this API—especially String, the wrapper classes (Integer, Double, etc.), and Math.
On many AP questions, you don’t need to memorize every method—what you need is the ability to:
- Recognize the difference between instance methods (called on an object, like
str.length()) and static methods (called on a class, likeMath.sqrt(9)) - Use method signatures correctly: name, parameters, and return type
- Reason about what a method call evaluates to
Reference types: variables don’t “hold the object”
In Java, class types like String are reference types. A variable of a reference type does not store the object’s contents directly. Instead, it stores a reference to an object somewhere in memory.
This matters because:
- Two variables can refer to the same object (aliasing)
- A reference variable can be
null(meaning it refers to no object) - Using a
nullreference like an object causes aNullPointerException
Example idea (not code yet): if a and b refer to the same String object, then calling methods on either one is “using” the same underlying object.
null and NullPointerException
The literal null represents “no object.” You can assign null to any reference variable:
String s = null;
But you cannot call methods on null:
System.out.println(s.length()); // NullPointerException
A common beginner misconception is thinking null is an “empty string.” It is not. An empty string is a real String object with length 0:
String empty = "";
System.out.println(empty.length()); // prints 0
Exam Focus
- Typical question patterns:
- You’re given code with object variables and method calls and must determine the output.
- You choose the correct method call based on a class’s behavior (often
StringorMath). - You identify what causes a runtime error (especially
NullPointerException).
- Common mistakes:
- Treating a reference variable as if it stores the object itself (confusing assignment/aliasing).
- Thinking
nullis the same as"". - Calling a method on a variable that might be
null.
Constructing Objects with Constructors
Creating an object: the role of new
To get an actual object, you usually use the keyword new. This allocates a new object in memory and returns a reference to it.
The general pattern looks like:
ClassName variableName = new ClassName(arguments);
The part that looks like a method call after new is a constructor.
Constructors: special “setup” code
A constructor is special code that runs when an object is created. Constructors:
- Have the same name as the class
- Do not have a return type (not even
void) - Can take parameters to initialize the object
Many classes provide multiple constructors with different parameter lists. This is called overloading.
For example, String has multiple ways to construct strings, but in AP CSA you most commonly see string literals like "AP" rather than explicit new String("AP").
Storing the reference in a variable
When you write:
String name = "Ada";
Java creates a String object (behind the scenes) and stores a reference to it in name. The variable name is not the characters themselves—it is a way to access the String object.
Aliasing: two variables, one object
Because variables store references, this can happen:
String a = "hello";
String b = a;
Now a and b refer to the same String object. With String specifically, you can’t change the object anyway (strings are immutable—more on that later), but aliasing becomes very important with mutable objects in later units.
Even in Unit 1, aliasing shows up conceptually: assignment between reference variables does not copy an object; it copies the reference.
A common library object: Scanner
Scanner is a Java library class used to read input. It’s not always heavily tested with interactive input on the AP multiple-choice section, but it’s a standard example of constructing and using an object.
import java.util.Scanner;
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
Here’s what’s happening step by step:
new Scanner(System.in)constructs aScannerobject configured to read from standard input.- The reference is stored in
scan. scan.nextInt()calls an instance method that returns anint.
If you ever see Scanner in a question, pay attention to the method return types: nextInt() returns an int, nextDouble() returns a double, and nextLine() returns a String.
When you don’t see new
Some objects appear without new in your code, for example System.out. System is a class, and out is a preexisting object (a static field) that you can call methods on, such as println.
So this:
System.out.println("Hi");
is still “calling a method on an object.” You just didn’t construct that object yourself.
Exam Focus
- Typical question patterns:
- Write one line of code that constructs an object with the correct constructor and stores it in a variable.
- Identify what object is created and what the variable stores (object vs reference).
- Trace code where reference variables are assigned to each other.
- Common mistakes:
- Forgetting
newwhen creating an object (writingScanner s = Scanner(System.in);). - Confusing constructors with methods (trying to use a return value from a constructor).
- Thinking
ClassName x = y;makes a copy of the object rather than copying the reference.
- Forgetting
Calling Methods: Void vs Non-void, Parameters, and Return Values
The dot operator: “ask this object to do something”
Most object interaction in Java uses the dot operator .:
objectReference.methodName(arguments)
This means: find the object referred to by objectReference, then run methodName on it.
Java chooses which method to run based on:
- The class of the object
- The method name
- The number and types of arguments (the method signature)
Parameters vs arguments
These two words are easy to mix up:
- Parameters are the variables in a method or constructor definition.
- Arguments are the actual values you pass in when you call it.
If a method is described as substring(int beginIndex, int endIndex), then beginIndex and endIndex are parameters. In s.substring(2, 5), the arguments are 2 and 5.
This matters on AP questions because they often test whether you know what type an argument must be (for example, that substring needs integer indices).
Void methods vs non-void methods
A method can either:
- Perform an action without giving a value back (void method)
- Produce a value (non-void method, also called a “returning” method)
Void method example:
System.out.println("Hello");
println prints as a side effect; it does not evaluate to a value you can store.
Non-void method example:
String s = "hello";
int n = s.length();
length() returns an int. That returned value can be stored, used in an expression, compared, etc.
A key rule: you can only assign a method call to a variable if the method returns a compatible type.
Using return values in expressions
Because non-void methods evaluate to a value, you can use them inside larger expressions:
String s = "computer";
int lastIndex = s.length() - 1; // length() gives an int
This kind of expression nesting is extremely common on AP CSA.
Method chaining
Sometimes a method returns an object, and you call another method on the returned object. This is called method chaining.
For example:
String result = "hello".toUpperCase().substring(1);
To understand this, you read it left to right:
"hello".toUpperCase()returns the string"HELLO".- On that returned string,
.substring(1)returns"ELLO".
Chaining is especially common with String methods.
A common mistake is assuming intermediate method calls “change” the original object. With String, they don’t—each call returns a new String.
Static methods: calling a method on a class
Some methods belong to a class itself rather than to an instance. These are static methods.
The Math class is the main example in this unit:
double r = Math.sqrt(16);
Notice there is no new Math() and no object variable. You call sqrt directly on the class name.
Students often try to write Math m = new Math();—that’s not how Math is designed.
Return type awareness: the skill AP loves to test
Many AP questions boil down to: “What is the type/value of this expression?” If you know method return types, you can reason correctly.
For example:
s.length()is anints.substring(1, 3)is aStringMath.random()is adouble
Exam Focus
- Typical question patterns:
- Determine the value (or type) of an expression containing method calls.
- Pick the correct line of code that uses a method’s return value properly.
- Trace method chaining and identify intermediate results.
- Common mistakes:
- Treating a void method as if it returns a value (trying to assign
println). - Forgetting parentheses when calling a method (
s.lengthinstead ofs.length()). - Mixing up instance vs static calls (writing
s.sqrt(9)orMath m = new Math()).
- Treating a void method as if it returns a value (trying to assign
The String Class: Text as Objects
Why String is central in Unit 1
Text shows up everywhere: user input, file contents, messages, names, and formatted output. Java represents text using the String class, which is one of the most frequently tested library classes on AP CSA.
When you work with String, you’re constantly using object methods—so it’s the perfect vehicle for learning how method calls, parameters, and return values work.
Strings are immutable
A crucial property: Strings are immutable, meaning once a String object is created, it cannot be changed.
So when you call a method like toUpperCase(), Java does not modify the existing string. Instead, it creates and returns a new String.
This matters because code like this does not do what beginners expect:
String s = "hi";
s.toUpperCase();
System.out.println(s); // still "hi"
You ignored the return value. To actually keep the uppercase version, you must assign it:
s = s.toUpperCase();
Indices: characters are numbered starting at 0
Many String methods use indices. In Java, indices start at 0, not 1.
For a string of length n, valid character indices go from 0 to n - 1.
If you use an index outside that range, you’ll get a StringIndexOutOfBoundsException at runtime.
Core String methods you must understand
Below are several String methods that frequently appear in AP CSA questions. The goal is not just memorizing names—it’s understanding what they return and how to interpret their parameters.
length()
- Returns the number of characters in the string as an
int.
String s = "AP CSA";
System.out.println(s.length()); // 6 (includes the space)
substring(...)
substring extracts part of a string and returns a new String.
Common forms:
substring(int beginIndex)returns frombeginIndexto the end.substring(int beginIndex, int endIndex)returns frombeginIndexup to (but not including)endIndex.
That “endIndex is exclusive” rule is one of the most tested details.
Example:
String s = "computer";
System.out.println(s.substring(3)); // "puter"
System.out.println(s.substring(1, 4)); // "omp"
Why substring(1, 4) is "omp":
- index 1: o
- index 2: m
- index 3: p
- stop before index 4
indexOf(...)
indexOf searches for a substring (or character) and returns the index of the first occurrence.
- If it’s not found, it returns
-1.
String s = "banana";
System.out.println(s.indexOf("na")); // 2
System.out.println(s.indexOf("z")); // -1
A common mistake is forgetting the -1 case. On AP questions, you often need to handle “not found” explicitly.
equals(...) vs ==
To compare the contents of strings, use equals:
String a = "hi";
String b = "hi";
System.out.println(a.equals(b)); // true
== compares whether two reference variables refer to the exact same object, not whether the text matches. Sometimes a == b will be true (due to string interning), sometimes not—so you should not rely on it.
This is a major AP CSA point: when comparing strings for equality, use equals.
compareTo(...)
compareTo compares strings in lexicographic (dictionary) order and returns an int:
- Negative if the calling string comes before the argument
- 0 if they are equal
- Positive if it comes after
You do not need to memorize the exact positive/negative value—only the sign and what it means.
System.out.println("ant".compareTo("bat")); // negative
System.out.println("bat".compareTo("bat")); // 0
System.out.println("cat".compareTo("bat")); // positive
toLowerCase() and toUpperCase()
These return new strings with changed letter case.
String s = "Ap";
String t = s.toLowerCase();
System.out.println(s); // "Ap"
System.out.println(t); // "ap"
Again, immutability is the key idea: s doesn’t change unless you reassign it.
Example: extracting the last character
To get the last character as a one-character string:
String s = "Java";
String last = s.substring(s.length() - 1);
System.out.println(last); // "a"
What can go wrong?
- If
sis empty (""), thens.length() - 1is-1, which is an invalid index.
Example: checking whether a string contains another string
You can use indexOf:
String s = "university";
boolean hasVers = s.indexOf("vers") >= 0;
System.out.println(hasVers); // true
This works because indexOf returns -1 when not found.
Exam Focus
- Typical question patterns:
- Predict the output of
substring,indexOf, and chainedStringmethod calls. - Choose the correct code to compare strings (
equalsvs==). - Determine what happens with boundary indices (0,
length(),length() - 1).
- Predict the output of
- Common mistakes:
- Treating the second
substringindex as inclusive instead of exclusive. - Using
==to compare string contents. - Off-by-one errors when using
length()to compute indices.
- Treating the second
Wrapper Classes and Autoboxing
Primitive types vs objects (the practical difference)
Java has primitive types (like int, double, boolean) and reference types (objects). Primitive values are not objects, so they don’t have methods.
But sometimes you need an object form of a primitive—for example:
- Some library classes and data structures store objects, not primitives.
- You may want to use useful static methods (like converting a numeric string to an integer).
That’s where wrapper classes come in.
What wrapper classes are
A wrapper class is a class that “wraps” a primitive value inside an object. Common wrappers in AP CSA:
IntegerwrapsintDoublewrapsdoubleBooleanwrapsboolean
You can create wrapper objects, but more often you’ll use their static methods.
Autoboxing and unboxing
Java can automatically convert between a primitive and its wrapper in many situations:
- Autoboxing: primitive to wrapper
- Unboxing: wrapper to primitive
Example:
Integer a = 7; // autoboxing (int -> Integer)
int b = a; // unboxing (Integer -> int)
This is convenient, but it can hide what’s actually happening, which can lead to subtle errors.
Useful Integer and Double methods
Parsing strings into numbers
A very common task is converting a numeric string to a number.
int x = Integer.parseInt("123");
double y = Double.parseDouble("3.14");
If the string isn’t a valid number format, these methods throw a NumberFormatException.
Converting numbers to strings
You’ll often see String.valueOf(...) (from the String class) or wrapper toString methods.
String s1 = String.valueOf(42);
String s2 = Integer.toString(42);
Comparing wrapper objects: don’t rely on ==
Just like with strings, == compares references for wrapper objects. Use equals to compare the wrapped values.
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // not reliable to reason about
System.out.println(a.equals(b)); // true
Even though Java sometimes reuses certain Integer objects behind the scenes, AP-style reasoning should be: == is for primitive equality; equals is for object content equality.
A dangerous pitfall: unboxing null
If you have a wrapper variable that is null and Java tries to unbox it to a primitive, you will get a NullPointerException.
Integer n = null;
int x = n; // NullPointerException due to unboxing
This shows up in code-tracing questions where a wrapper might not have been initialized.
Exam Focus
- Typical question patterns:
- Convert between strings and numeric types using
parseInt/parseDouble. - Identify the type/value produced by an expression involving wrappers and primitives.
- Recognize when
equalsis needed for object comparisons.
- Convert between strings and numeric types using
- Common mistakes:
- Using
==to compare wrapper objects. - Forgetting that parsing can throw an exception if the format is invalid.
- Unboxing a
nullwrapper into a primitive.
- Using
The Math Class and Random Numbers
Why Math is different: static utility methods
The Math class provides common mathematical functions. Unlike String, you don’t create Math objects. You call methods directly on the class:
double a = Math.abs(-5.0);
double r = Math.sqrt(49);
These are static methods. The mental model is: Math is a toolbox; you don’t need to build a toolbox object to use a hammer.
Common Math methods in AP CSA
You should be comfortable recognizing what these do and what type they return.
Math.abs(x)returns the absolute valueMath.pow(a, b)returns a^b as adoubleMath.sqrt(x)returns the square root as adoubleMath.max(a, b)andMath.min(a, b)return the larger/smaller of two numbers
Be careful with return types: even when you pass integers to pow or sqrt, the result is a double.
Rounding and casting
Java has multiple rounding-related tools:
- Casting
(int)truncates toward 0 (it does not round). Math.round(x)rounds to the nearest integer-like value, but returnslongfordoubleinput.
Example showing truncation:
double x = 9.9;
int t = (int) x;
System.out.println(t); // 9
Students often think casting rounds; it doesn’t.
Math.random() and the idea of a range
Math.random() returns a double in the range:
- Greater than or equal to
0.0 - Less than
1.0
So it’s in [0.0, 1.0).
That matters because you can scale it to generate random numbers in other ranges.
Random integer from 0 to n-1
To get a random integer from 0 to n - 1:
r = (int)(Math.random() * n)
Explanation:
Math.random()gives adoublefrom 0.0 up to (but not including) 1.0.- Multiplying by
ngives adoublefrom 0.0 up to (but not including)n. - Casting to
inttruncates, producing one of0, 1, 2, ..., n - 1.
Example:
int die = (int)(Math.random() * 6) + 1; // 1..6
System.out.println(die);
Notice the + 1 shifts the range.
Random integer from a to b (inclusive)
If you want a random integer between a and b, inclusive, with a <= b, the size of the range is b - a + 1. A common pattern is:
r = (int)(Math.random() * (b - a + 1)) + a
This pattern is frequently tested conceptually: AP questions may ask which expression correctly generates a number in a given range.
What can go wrong with random ranges
Typical bugs include:
- Forgetting the
+ 1when the upper bound should be inclusive - Putting the cast in the wrong place, like
(int)Math.random() * nwhich becomes0 * nmost of the time because(int)Math.random()is always 0
Compare these:
(int)(Math.random() * 10) // 0..9 (correct)
(int)Math.random() * 10 // always 0 (wrong)
The parentheses determine what gets truncated.
Exam Focus
- Typical question patterns:
- Identify the correct expression to generate a random integer in a specified range.
- Trace code that mixes
Mathmethods, casting, and integer division. - Determine output types (for example, that
Math.sqrt(9)isdouble).
- Common mistakes:
- Casting too early in a
Math.random()expression. - Confusing truncation with rounding.
- Forgetting that many
Mathmethods returndoubleeven with integer inputs.
- Casting too early in a
Putting It Together: Reading, Tracing, and Writing Code with Objects
The core workflow: create (or receive) an object, then use methods
Most Unit 1 code fits a simple pattern:
- You have a reference to an object (maybe created with
new, maybe provided likeSystem.out) - You call methods on it
- You use returned values to compute other results
- You store results in variables or print them
The AP exam frequently tests your ability to read these steps accurately—especially when method calls are nested.
Expression tracing with method calls
When tracing code, treat each method call as producing a value (for non-void methods) or producing a side effect (for void methods). A reliable approach is:
- Evaluate inside parentheses first
- Replace non-void method calls with their returned values
- Keep track of variable updates (reassignment)
Worked tracing example (Strings + indices)
Consider:
String s = "mississippi";
int i = s.indexOf("iss");
String t = s.substring(i, i + 4);
System.out.println(t);
Step-by-step:
sis"mississippi"s.indexOf("iss")finds the first occurrence of"iss"- In
"mississippi", the first"iss"starts at index 1 - So
ibecomes 1
- In
s.substring(i, i + 4)becomess.substring(1, 5)- That extracts indices 1, 2, 3, 4
- Characters: i s s i
- So
tis"issi"
- It prints
issi
What can go wrong?
- Miscounting indices (forgetting the string starts at 0)
- Treating the substring end index as inclusive (it’s exclusive)
Writing small code snippets that use objects correctly
AP questions often ask you to write a few lines (not whole programs). When writing these snippets, focus on:
- Correct method names and parentheses
- Correct argument types and order
- Correct use of return values
- Correct variable types
Example: compute the initial of a first name
Task: Given String first, create a String initial containing the first letter (as a one-character string).
Reasoning:
- The first character is at index 0.
- To extract one character as a string, you can use
substring(0, 1).
String initial = first.substring(0, 1);
Common error: using substring(0, 0) (that returns the empty string).
Example: safely checking for a substring
Suppose you want to check whether word contains "cat".
boolean containsCat = word.indexOf("cat") != -1;
This uses the contract of indexOf: return -1 when not found.
Mixing primitives and objects: pay attention to types
Unit 1 frequently mixes int, double, and String.
Examples of type-sensitive behavior:
"score: " + 5becomes aStringdue to concatenation.5 / 2is integer division (result2), but5 / 2.0is2.5.
Even though integer division is often emphasized earlier/later depending on course sequence, it appears naturally when you combine methods like length() (an int) with arithmetic.
Side effects vs returned values (a mindset that prevents bugs)
When you call a void method, the only “result” is what it does (printing, changing an object’s state, etc.). When you call a non-void method, the method produces a value you can use.
With String, most methods are non-void and have no side effects because strings can’t change. With other objects (like Scanner), method calls can change the object’s internal state (for example, moving past tokens in the input). This difference becomes more important later, but Unit 1 is where you start building the habit of asking:
- Does this method return something I need to store?
- Does this method change the object I’m calling it on?
A realistic combined example (Math + String)
Suppose you want a random uppercase letter.
Reasoning:
- Generate random integer 0..25.
- Map 0..25 to ASCII codes 65..90 is possible, but AP CSA often avoids requiring ASCII memorization.
- Another approach: store alphabet in a string and use
substring.
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int index = (int)(Math.random() * 26);
String letter = alphabet.substring(index, index + 1);
System.out.println(letter);
What can go wrong?
- If you accidentally use
alphabet.substring(index, index)you get"". - If your random range is wrong (like 0..26),
index + 1might be out of bounds.
Exam Focus
- Typical question patterns:
- Trace multi-line code that combines method calls and arithmetic to determine final output.
- Fill in a missing line so a code segment produces the intended result.
- Identify the first line that would cause a runtime error (often index or
nullrelated).
- Common mistakes:
- Losing track of types in nested expressions (trying to store a
doublein anintwithout casting, or using aStringwhere anintis required). - Off-by-one errors when computing indices from
length(). - Ignoring return values from non-void methods (especially
Stringmethods), expecting the original object to change.
- Losing track of types in nested expressions (trying to store a