Beginner 20 min read

Recursion: A First Look

By the end of this lesson, you'll be able to:

  • Explain what a recursive method is
  • Identify the base case that stops a recursive method
  • Trace through a simple recursive call step by step

Prerequisites: "Method Overloading"

A method that calls itself

public Integer factorial(Integer n) {
    if (n <= 1) {
        return 1; // base case
    }
    return n * factorial(n - 1); // recursive case
}

System.debug(factorial(4)); // 24

Here's what each line is doing (line numbers match the code above, and are display-only — copy the code and it still runs with no numbers in it):

  1. public Integer factorial(Integer n) { — declares a method named factorial. public means other code in the org can call it, Integer before the name is what it returns, and (Integer n) is its one parameter: a whole number, referred to as n inside the method.
  2. if (n <= 1) { — a condition checked every time factorial runs. <= means "less than or equal to." This line asks: has n counted down to 1 (or below)?
  3. return 1; // base case — if line 2 was true, the method stops immediately and hands back 1, without calling factorial again. This is the base case: the one path through the method that doesn't call itself, and the only reason the recursion ever ends.
  4. } — closes the if block from line 2.
  5. return n * factorial(n - 1); // recursive case — only reached when line 2 was false. This is the recursive case: it calls factorial again, with a smaller number (n - 1), and multiplies whatever that call eventually returns by the current n. The method is calling a smaller version of itself.
  6. } — closes the method body from line 1.
  7. (blank line, separating the method definition above from the code that uses it below)
  8. System.debug(factorial(4)); // 24 — calls factorial with 4 and logs whatever it returns.

Tracing factorial(4) step by step:

Each call checks line 2 first. If it's false, the call has to pause and wait for a smaller call to finish before it can compute its own line 5:

  • factorial(4): is 4 <= 1? No. Calls factorial(3) and waits.
  • factorial(3): is 3 <= 1? No. Calls factorial(2) and waits.
  • factorial(2): is 2 <= 1? No. Calls factorial(1) and waits.
  • factorial(1): is 1 <= 1? Yes — the base case. Line 3 returns 1 immediately. Nothing waits on this one; it's the first call to actually finish.

Now the paused calls resume, in reverse order, each finishing its own line 5 using the value it was waiting on:

  • factorial(2) resumes: 2 * 1 = 2. Returns 2.
  • factorial(3) resumes: 3 * 2 = 6. Returns 6.
  • factorial(4) resumes: 4 * 6 = 24. Returns 24.

Line 8 receives that 24 and debugs it — matching the // 24 comment in the code.

Why the base case is non-negotiable

Without if (n <= 1) { return 1; }, factorial would call itself forever — factorial(4) → factorial(3) → factorial(2) → factorial(1) → factorial(0) → factorial(-1) → ... Apex would eventually hit a stack depth limit and throw an error. Every recursive method needs a condition that stops the self-calls, exactly like a loop needs a condition that eventually becomes false.

A real-world analogy: Russian nesting dolls

Opening a set of nesting dolls means repeating the same action — open, look inside, open the next one — until you reach the smallest doll that doesn't open at all. That smallest doll is the base case; every doll before it is the recursive case, doing the same simple action and handing the "next problem" to the doll inside it.

Trade-offs and when NOT to use this

Recursion often reads more elegantly than an equivalent loop for naturally nested problems, but every recursive call adds to Apex's call stack, and deep recursion can hit governor limits faster than an equivalent loop would. For simple counting or accumulation like this factorial example, a for loop (Module 7) is usually just as clear and safer at scale — recursion earns its keep on genuinely nested structures, which later modules will revisit.

Exercise

Write a recursive method Integer sumUpTo(Integer n) that returns the sum of all integers from 1 to n (e.g., sumUpTo(4) returns 10). Include a base case for n <= 1.

Show hint

return n + sumUpTo(n - 1); with a base case returning 1 when n <= 1.

Salesforce: ○ Not connected Connect
APEX

Execution Results

Run your code to see the result.

Recursion: A First Look Quiz

1. What is a base case in recursion?

2. Recursion is always safer than a loop for avoiding governor limits.

Log in to submit the quiz and save your score.

Leaderboard

  • 1. Monde Masiza 2/2

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

A recursive method calls itself to solve a smaller version of the same problem — powerful for naturally nested data, but only safe with a clear stopping point.