🧩
Basics

Methods & Recursion

Reusable Blocks of Code
💡 A method is a reusable machine — build it once, and whenever you need it, just "call" it and the work gets done. Recursion is a machine that calls itself again and again, until it stops.

A method takes parameters, does its job, and (optionally) returns a value — saving you from repeating code.

Java follows "pass by value" — a method gets a copy of the values, the original variable never changes (for objects, it gets a copy of the reference).

In recursion, a method calls itself — like factorial(5) = 5 * factorial(4)... until the base case (factorial(1)=1) is reached.

int factorial(int n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}
🧩
A method is a reusable machine — build it once, and whenever you need it, just "call" it and the work gets done. Recursion is a machine that calls itself again and again, until it stops.
1 / 6
⚡ Quick Recap
  • Method = a reusable code block
  • Pass by value — you get a copy
  • Recursion = a method calling itself
On this page (4 subtopics)

A method's signature is its name + parameter types/order (the return type is NOT part of the signature — which is why two methods can't differ by return type alone, they must differ by parameters to be overloaded).

void means the method returns nothing. If a method returns something (like int, String, or an object), a return statement is required on every possible code path — the compiler checks that no path can end the method without a return, otherwise you get a "missing return statement" error.

💡Tip: Name methods after the action they perform (calculateTotal, isValid, getName) — this makes code self-documenting, reducing the need for comments.

... (three dots) lets a method take a variable number of arguments — internally it's treated like an array inside the method. The caller can flexibly pass 0, 1, or as many arguments as they like.

A method can have only one varargs parameter, and it must always be the *last* parameter (if there are other regular parameters too). Built-in methods like System.out.printf() and String.format() use varargs themselves.

int sum(int... nums) {
  int total = 0;
  for (int n : nums) total += n;
  return total;
}
sum(1, 2, 3);       // works
sum(1, 2, 3, 4, 5); // works bhi
sum();               // works, total = 0

Java is always pass-by-value, whether it's a primitive or an object — this is a very common interview trick question. For primitives, you get a copy of the value (the original never changes, no matter what you do inside the method).

For objects, you get a copy of the "reference" (the heap address) — meaning both (the original variable and the parameter) point to the same object. So you can change fields inside the object (visible outside too), but if you reassign the parameter to a new object (s = new Student()), only the local copy is updated — the original reference doesn't change.

void modify(Student s) {
  s.name = "Changed";   // ye dikhega original object mein (same reference)
  s = new Student();    // ye NAHI dikhega — sirf local copy reassign hui
}
⚠️Common Mistake: Saying "Java is pass-by-reference" is wrong! Java is always pass-by-value — for objects, "the value of the reference" is passed, which is a different thing. This distinction gets asked over and over in interviews.

Factorial and Fibonacci are classic recursion examples. Every recursive method needs two things: a base case (where recursion stops) and a recursive case (which shrinks the problem and calls itself).

Without a base case, a method will keep calling itself infinitely, until a StackOverflowError occurs — every recursive call takes up a "stack frame", and the JVM's call stack has a fixed size.

The naive recursive version of Fibonacci (as below) is very inefficient for large n — because the same values get calculated over and over (fibonacci(5) calculates fibonacci(3) twice). Ways to fix this include "memoization" (caching results) or an iterative approach.

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

int fibonacci(int n) {
  if (n <= 1) return n;
  return fibonacci(n-1) + fibonacci(n-2);
}
💡Tip: Whenever you write a recursive method, think about the base case first, then the recursive case. This "base case first" habit will save you from infinite recursion bugs.