Java Tutorial Series: This lesson is part of our comprehensive Complete Java Tutorial: Learn Java from Beginner to Advanced.

Recursion in Java: How Recursive Methods Work, Examples and Best Practices

What Is Recursion in Java?

Recursion is a technique in which a method calls itself to solve a smaller version of the same problem. A correct recursive solution needs a base case and a recursive case that moves the input toward that base case.

The Base Case

static void countdown(int n) {
    if (n == 0) {
        return;
    }
    System.out.println(n);
    countdown(n - 1);
}

When n becomes zero, the method returns instead of calling itself again.

The Recursive Case

The recursive case performs part of the work and calls the method again with a smaller or simpler problem. Progress toward the base case is essential.

Call Stack

Each recursive call creates a stack frame containing the method's state. Calls continue until the base case is reached, then the frames return in reverse order. This explains why deeply recursive programs can consume significant stack space.

Factorial Example

static int factorial(int n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

factorial(5) reduces the problem through 4, 3, 2 and 1 before returning the calculated result.

Sum Example

static int sum(int n) {
    if (n <= 0) {
        return 0;
    }
    return n + sum(n - 1);
}

Recursion and Arrays

A recursive method can carry an index to process an array one element at a time. This is useful for learning recursive reasoning, although an ordinary loop may be simpler for a straightforward linear scan.

Divide-and-Conquer

Recursion is especially important for divide-and-conquer algorithms. Problems such as merge sort and recursive binary search divide the problem into smaller pieces and combine or evaluate their results.

Recursion vs Iteration

Many recursive solutions have iterative alternatives. Iteration often avoids growing the call stack, while recursion can provide a natural representation for trees, hierarchical structures, backtracking and divide-and-conquer problems.

Stack Overflow

If recursion does not reach a base case, or if the recursion depth becomes too large, the program can throw StackOverflowError. The recursive step must make measurable progress toward termination.

Performance and Complexity

Do not assume recursion is efficient simply because the code is short. A recursive method can perform repeated work or create many stack frames. Analyze time and space complexity before using it for large inputs.

Fibonacci Example

static int fibonacci(int n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

This simple example demonstrates recursion, but it also shows why repeated recursive work can become inefficient for larger inputs.

Common Mistakes

Missing base cases, recursive calls that do not reduce the problem, incorrect return values, excessive depth and assuming recursion is always better than a loop are common mistakes.

Best Practices

Write the base case first, prove that every recursive call moves toward it, test very small inputs, inspect call depth and consider an iterative or optimized alternative when performance requires it.

Where Recursion Is Useful

Recursion is common in tree traversal, graph-related algorithms, backtracking, divide-and-conquer sorting and problems whose mathematical or structural definition is recursive.

Practice Problems

Implement factorial, sum, power, recursive string reversal, binary search, greatest common divisor and a simple tree traversal.

Frequently Asked Questions

What is recursion? A method solving a problem through smaller calls to itself.

What stops recursion? A reachable base case.

What happens without one? Calls can continue until stack space is exhausted.

Is recursion always better? No; choose based on clarity, structure and performance.

Conclusion

Recursion is an important way of thinking about algorithms. Once you understand base cases, recursive progress and the call stack, you are prepared for more advanced searching, sorting, trees and algorithmic problem solving.

Learn More

  • Java Syntax
  • Java Variables
  • Java Data Types
  • Java Operators
  • Java Input and Output
  • Java Methods
  • Java Arrays and Collections

Continue Learning Java

After this topic, continue through the Java control-flow path by practicing the next related statement or loop. Build small programs rather than only reading examples.

Deeper Practical Coverage

Designing a Recursive Algorithm

Before writing recursive code, identify three things: the smallest solvable input, the transformation that makes the input smaller, and how the results of smaller calls combine into the current result.

For factorial:
– Base case: n <= 1
– Smaller problem: n – 1
– Combination: n * factorial(n – 1)

Recursive Call Stack

Suppose factorial(4) is called. Java creates a frame for factorial(4), which calls factorial(3), which calls factorial(2), which calls factorial(1). Once factorial(1) returns, the previous frames resume one by one. This explains both how recursion works and why deep recursion consumes stack space.

Multiple Recursive Calls

Some algorithms make more than one recursive call. Fibonacci is a classic example, but naive Fibonacci is intentionally useful as a performance lesson because it repeats the same subproblems.

Memoization stores results so that the same subproblem does not need to be solved repeatedly.

Recursion and Backtracking

Backtracking explores choices recursively and reverses a choice when it leads to an invalid path. Common examples include generating combinations, solving mazes, and exploring permutations. The recursive call represents moving deeper into the current decision path.

Tree Traversal

Trees are naturally recursive structures: a node can contain a left subtree and a right subtree, each of which is itself a tree. This makes recursive traversal particularly readable.

static void preorder(Node node) {
    if (node == null) return;
System.out.println(node.value);
    preorder(node.left);
    preorder(node.right);
}

The same idea extends to inorder and postorder traversal.

Binary search reduces a sorted search range by approximately half on every recursive call. The important details are the base case when the range is empty and the calculation of the midpoint without unnecessarily risking integer overflow.

Memoization

When a recursive algorithm repeatedly solves the same subproblem, memoization can store previously computed results. This changes the practical performance of many problems dramatically, although it also adds memory usage.

Recursion and Stack Limits

Recursion depth is limited by available stack space. Java does not generally eliminate tail-recursive calls automatically, so an algorithm that may recurse hundreds of thousands of levels should normally be redesigned iteratively or with an explicit stack data structure.

Interview Perspective

Typical recursion questions ask you to identify the base case, trace calls, determine time and space complexity, convert recursion to iteration, or recognize overlapping subproblems. Practice drawing the call stack for small inputs before attempting large examples.

Extended Practice Set

  • Write factorial recursively.
  • Write recursive sum.
  • Implement recursive binary search.
  • Trace Fibonacci calls.
  • Convert a recursive algorithm to iteration.
  • Identify base and recursive cases in a tree traversal.

Java Language and Version Note

The Java platform documentation groups control flow into decision-making, looping, and branching constructs. Modern Java has also expanded switch with expression forms, arrow rules, and pattern-oriented capabilities. When publishing this article, the website should state the Java version when an example depends on a newer language feature. Core syntax such as if, if-else, for, while, do-while, break, continue, and traditional switch remains foundational, while newer forms should be presented as version-aware additions.