Lesson 5: Classes and ObjectsAP
🎧 Listen to this lesson
A class is a blueprint; an object is something built from it. Unit 2 (Using Objects) introduces objects through the library classes you call every day — String and Math — and Unit 5 (Writing Classes) has you design your own. This lesson covers the object model itself: references, instantiation, method calls, and why two variables can point at one object. Everything in Units 5 through 9 is a consequence of the ideas here.
Objects, references, and new
Declaring Circle c; does not create a circle. It creates a reference variable — a name that can hold the address of a Circle object, and initially holds null (no object). The object itself is created by new:
Circle c = new Circle(5.0); // construct an object; c refers to it
double a = c.area(); // call a method on the object through the reference
Calling a method on a null reference throws a NullPointerException — the most common runtime crash in real Java programs, and a concept the exam tests by asking which line of a segment fails. Method calls pass actual parameters (arguments) into the method's formal parameters; for objects, what is passed is a *copy of the reference*, so a method can mutate the object it receives, but cannot reseat the caller's variable to a different object.
String: the object you already know
String is a class, and strings are objects with methods — length(), substring(from) and substring(from, to) (start inclusive, end exclusive), indexOf(str) (returns -1 when absent), equals, and compareTo. Strings are immutable: no method changes a string; methods like substring return a *new* string. Forgetting that is a perennial bug:
String s = "computer";
s.substring(0, 4); // computes "comp" and THROWS IT AWAY
System.out.println(s); // still "computer"
s = s.substring(0, 4); // now s is "comp"
Track a sequence of String calls the way you would trace a loop:
| Statement | Value returned | Value of word after |
|---|---|---|
| (start) | — | "science" |
word.substring(2) | "ience" | "science" (unchanged) |
word = word.substring(0, 3) | "sci" | "sci" |
word.indexOf("c") | 1 | "sci" |
word + "!" | "sci!" | "sci" (result not stored) |
The Math class: static methods and random numbers
Math is used without objects: its methods are static, called through the class name — Math.sqrt(16) is 4.0, Math.abs(-7) is 7, Math.pow(2, 10) is 1024.0, Math.max(a, b) picks the larger. The exam's favourite is Math.random(), which returns a double in the range 0.0 ≤ value < 1.0 (1.0 never occurs). Scale and shift it to build any range:
(int) (Math.random() * 6)→ 0 through 5(int) (Math.random() * 6) + 1→ 1 through 6 (a die)(int) (Math.random() * range) + min→ min through min + range − 1
The cast truncates the scaled double, which is exactly what distributes the values evenly. Getting the range arithmetic right — how many values, starting where — is a guaranteed exam appearance every year.
Aliasing: two names, one object
Because variables hold references, assignment copies the *reference*, not the object:
Circle a = new Circle(5.0);
Circle b = a; // b refers to the SAME object as a
b.setRadius(9.0);
System.out.println(a.getRadius()); // 9.0 — a sees the change!
There is only one circle here. Aliasing explains a family of exam questions (and real bugs, when a method unexpectedly mutates a shared object). By contrast, new Circle(5.0) always builds a fresh, independent object. Parameters behave the same way: passing an object to a method gives the method another reference to the same object.
Real-world design: objects model the problem
Object-oriented design starts by asking "what are the *things* in this problem, what do they know, and what can they do?" A library system has Book objects that know their title and borrower, and can be checked out; a game has Player objects that know their position and can move. The data (instance variables) and the behaviour (methods) travel together, so the code that changes a book's state lives in exactly one place. When state and behaviour were kept apart (the older procedural style), every part of a program could touch every piece of data — the aliasing problem at industrial scale.
new creates objects; assignment and parameter passing copy references; null means "no object yet" and any method call on it crashes.Common mistakes (from examiner reports)
- Discarding returned values.
s.substring(0, 3);alone does nothing — Strings are immutable, so results must be assigned or used. - substring end confusion.
substring(1, 4)returns characters at indices 1, 2, 3 — the end index is exclusive. The length of the result isto − from. - Comparing objects with
==. Useequalsfor content (Unit 3's rule, caused by this unit's reference model). - Random range errors.
(int) (Math.random() * 6 + 1)can give 1–6 but with a subtle flaw (the +1 is inside the cast and the distribution is still fine — the real errors are* 7for a die, giving 0–6 after casting, or forgetting the cast so the value stays adouble). - Calling an instance method through the class.
Circle.area()does not compile; instance methods need an object:c.area(). Only static methods (likeMath's) are called through the class name. - Assuming assignment copies objects.
b = ashares; it never clones.
(int) (Math.random() * 11) - 5 produce? (−5 through 5 — eleven values, a classic "random temperature swing".)AP Exam Experience
Question 1. Consider the following code segment.
String phrase = "data structures";
System.out.println(phrase.substring(5, 9) + phrase.indexOf("a"));
What is printed?
- (A)
stru1 - (B)
stru3 - (C)
data1 - (D)
stru2 - (E)
stru0
Answer: (A). Indices: d0 a1 t2 a3 ' '4 s5 t6 r7 u8 c9... — substring(5, 9) takes indices 5–8, "stru". indexOf("a") finds the first "a", at index 1. Concatenation gives stru1. (D) traps students who use the last "a".
Question 2. Which of the following expressions produces a random integer in the range 10 to 20, inclusive, with each value equally likely?
- (A)
(int) (Math.random() * 10) + 10 - (B)
(int) (Math.random() * 11) + 10 - (C)
(int) (Math.random() * 20) + 1 - (D)
(int) (Math.random() * 10) + 11 - (E)
(int) (Math.random() * 21)
Answer: (B). The range 10–20 contains 11 values, so multiply by 11 (giving 0–10 after the cast), then shift by 10. (A) tops out at 19; (D) starts at 11 and ends at 20 but can never produce 10 — wait, check: * 10 gives 0–9, +11 gives 11–20, so 10 is missing; (E) gives 0–20.
Question 3. Consider the following code segment, where Counter has a method increment() that adds 1 to its count and getCount() that returns it.
Counter c1 = new Counter();
Counter c2 = c1;
c1.increment();
c2.increment();
System.out.println(c1.getCount());
What is printed?
- (A)
0 - (B)
1 - (C)
2 - (D)
3 - (E) The code does not compile.
Answer: (C). c2 = c1 copies the reference — there is only one Counter object, incremented twice through two names. (B) is the answer students give when they imagine assignment copies the object.
Free-Response Question. Write the complete class Book, representing a book in a school library. The class must satisfy the following:
- Instance variables: a
Stringfor the title, aStringfor the author, and anintfor the number of pages. All must be private. - A constructor that takes the title, author and page count (in that order) and initialises the object.
- A method
getTitle()that returns the title. - A method
isLong()that returnstrueif the book has more than 300 pages andfalseotherwise. - A method
describe()that returns aStringof the form"Dune by Frank Herbert (412 pages)"for a book with those values.
Scoring guideline (9 points).
- +1 All three instance variables declared
privatewith correct types - +1 Constructor header matches the class name with parameters in the specified order (String, String, int)
- +1 Constructor assigns all three parameters to the instance variables
- +1
getTitle()returns the title (return, not print) - +1
isLong()returns aboolean - +1
isLong()uses the correct boundary: strictly more than 300 pages - +1
describe()returns aStringbuilt by concatenation - +1
describe()output matches the specified format exactly, including "by", parentheses and "pages" - +1 Class compiles as a complete, self-contained class (no
main, correct braces)
Model solution.
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 boolean isLong()
{
return pages > 300;
}
public String describe()
{
return title + " by " + author + " (" + pages + " pages)";
}
}
## Going deeper: strings, randomness, and a complete worked example
The Unit 2 skills combine constantly: build a tiny fortune-teller that picks a random word from a sentence based on its length.
String s = "java is fun"; int len = s.length(); // 11 int pos = (int) (Math.random() * len); // 0..10 String ch = s.substring(pos, pos + 1); // one character at pos System.out.println(pos + ": " + ch);
Three traps are hiding here, all previously flagged: the random expression yields `0` through `len - 1` (never `len`), which is exactly the legal index range — add 1 carelessly and `substring` throws; `substring(pos, pos + 1)` extracts exactly one character because the end is exclusive; and `pos + ": "` concatenates left to right, converting the int to text.
**Bonus question.** For the code above, which of the following is a possible output?
- (A) `11: n`
- (B) `10: n`
- (C) `3: s`
- (D) `0: j`
- (E) Both (B) and (D) are possible.
**Answer: (E).** `pos` ranges over 0–10 inclusive: index 10 is 'n' (the last character of "java is fun": j0 a1 v2 a3 ' '4 i5 s6 ' '7 f8 u9 n10) and index 0 is 'j'. (A) fails because `pos` can never be 11; (C) fails because index 3 is 'a', not 's'.
📊 Interactive
Interactive — hover or explore the chart above.
🎬 Watch & Learn
Free YouTube video lessons on “Classes and Objects” — pick a result below: