CompSci.rocks
FRQcsapa

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 double arithmetic throughout
  • Official category: "Classes" — always FRQ 2 on the AP CSA exam

The Setup

  • No class skeleton is provided — the entire Bottle class 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) removes amountUsed mL 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

  1. Decide what state needs to persist: the bottle's fixed capacity, and the amount currently in it.
  2. In the constructor, store the capacity and set the current amount equal to it (starting full).
  3. 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.
  4. 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 = capacity in the constructor — this is what makes a newly built bottle start completely full, exactly as the problem specifies.
  • Subtracting amountUsed before 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 — since capacity never changes after construction, this always reflects 25% of the original capacity, not 25% of whatever amount happens 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 <. The shampoo.updateAmount(30.0) example specifically lands at exactly 25% and must not refill — using <= would incorrectly trigger a reset here.
  • Recomputing capacity * 0.25 from a changed value. Since capacity is fixed at construction and never reassigned, this isn't actually a risk here as written — but assigning capacity anywhere outside the constructor would silently break the 25% threshold for the rest of the bottle's life.
  • Forgetting to return amount at 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.

Related FRQs