FRQ
› csapa
Bottle: 2026 FRQ 2
A step-by-step solution to the 2026 AP CSA FRQ 2 (Bottle), covering designing a class around a percentage-based refill threshold in Java.
A bottle that automatically refills itself once it runs low is the whole idea behind this AP Computer Science A free-response question — the entire challenge is designing a class from scratch around one percentage-based rule.
What This FRQ Tests
- AP CSA units: Unit 5 (Writing Classes)
- Core skill: designing a class's fields and constructor from a plain-English description, with nothing already scaffolded
- Secondary skill: computing and comparing against a percentage of a stored value, correctly using
doublearithmetic throughout - Official category: "Classes" — always FRQ 2 on the AP CSA exam
The Setup
- No class skeleton is provided — the entire
Bottleclass is up to you to design. - The constructor takes the bottle's capacity in mL (a
double, guaranteed>= 0). A new bottle always starts completely full. updateAmount(double amountUsed)removesamountUsedmL from the bottle (the parameter is always positive and never more than what's left), then:- If the amount remaining after that removal would drop below 25% of the capacity, the bottle is immediately refilled back to full capacity instead.
- Either way, the method returns however much is in the bottle at the end.
Building the Bottle Class
Step-by-Step Approach
- Decide what state needs to persist: the bottle's fixed
capacity, and the amount currently in it. - In the constructor, store the capacity and set the current amount equal to it (starting full).
- In
updateAmount, subtract the used amount first, then check whether what's left has dropped below the 25% threshold — if so, reset back to full capacity instead. - Return the current amount either way.
The Code
public class Bottle
{
private double capacity;
private double amount;
public Bottle(double capacity)
{
this.capacity = capacity;
amount = capacity;
}
public double updateAmount(double amountUsed)
{
amount = amount - amountUsed;
if (amount < capacity * 0.25)
{
amount = capacity;
}
return amount;
}
}
Why Each Piece Matters
amount = capacityin the constructor — this is what makes a newly built bottle start completely full, exactly as the problem specifies.- Subtracting
amountUsedbefore checking the threshold — the rule is about what's left after the removal, not before it, so the check has to come second. capacity * 0.25, computed fresh each call — sincecapacitynever changes after construction, this always reflects 25% of the original capacity, not 25% of whateveramounthappens to be at the moment.- Strict
<, not<=— a remaining amount that lands at exactly 25% should not trigger a refill; only dropping below that threshold does.
Tracing the Example
Using the question's own execution sequence, shampoo = new Bottle(40.0) (25% of 40 is exactly 10.0):
| Call | amount after subtracting |
Below 25% (< 10.0)? |
Returned |
|---|---|---|---|
shampoo.updateAmount(30.0) |
10.0 | no (10.0 < 10.0 is false) |
10.0 |
shampoo.updateAmount(1.0) |
9.0 | yes | refills to 40.0, returns 40.0 |
The first call is the important edge case: landing at exactly 25% does not trigger a refill, which is only possible because the comparison uses strict < rather than <= — matching the question's table exactly, where 10.0 is returned with no reset.
Common Mistakes to Avoid
- Checking the threshold before subtracting
amountUsed. The rule is about the amount that would result from this removal, not the amount before it happens. - Using
<=instead of<. Theshampoo.updateAmount(30.0)example specifically lands at exactly 25% and must not refill — using<=would incorrectly trigger a reset here. - Recomputing
capacity * 0.25from a changed value. Sincecapacityis fixed at construction and never reassigned, this isn't actually a risk here as written — but assigningcapacityanywhere outside the constructor would silently break the 25% threshold for the rest of the bottle's life. - Forgetting to
return amountat the end — the method needs to report the amount either way, whether or not a refill happened.
Key Takeaways
- A refill/reset threshold based on a percentage of a fixed value should always be computed from that fixed field directly (
capacity * 0.25), not from a value that changes over time. - An edge case that lands exactly on a boundary (here, exactly 25%) is the detail most likely to reveal whether a comparison should be strict (
<) or inclusive (<=) — check any example that hits the boundary exactly before assuming either one. - When no class skeleton is given, the constructor parameter and the worked example table together tell you exactly what fields the class needs — work backward from what each method call is expected to return.