How does recursion work in Java, and what are the two conditions every recursive method needs?
Recursion is a method that calls itself with a smaller or simpler version of the same problem, until the problem is trivial enough to answer directly. Two ingredients are mandatory. The base case is the condition under which the method returns an answer without calling itself again; without it the recursion never terminates. The recursive case is the branch that makes the call, and it must move the problem towards the base case — otherwise you have infinite recursion and a StackOverflowError.
Mechanically, each call pushes a frame onto the call stack holding that invocation's parameters and locals. When the base case is reached, the frames unwind, each one combining its partial result with the value returned from the frame below it. So recursion has a cost: one stack frame per level, which is the trade-off you pay for not needing an explicit collection to hold intermediate state.
The JVM does not perform tail-call optimisation. A method whose last statement is a recursive call still consumes a stack frame per call, so writing recursion in tail position does not save you from stack overflow. That is a genuine difference from functional languages such as Scala, and it is worth stating because it is the standard reason to convert a deep recursion into a loop.
Recursion is the right tool when the problem has a naturally recursive structure — traversing a tree, walking a directory, flattening a nested list, evaluating an expression — because the code mirrors the shape of the data. It is the wrong tool for linear tasks such as summing a list, where a loop is simpler and uses constant stack depth.