Infinite recursion repeatedly enters the same recursive path without satisfying its termination condition. Unlike finite recursion that eventually changes state and exits, it eventually exhausts available stack space; changing state is not enough if the condition remains unreachable. section 5.4.2
A mistaken delegation call
A button wrapper intends to delegate to its wrapped button, but calls onPressed() without the delegate qualifier. When enabled, the wrapper calls itself indefinitely. The same failure pattern can arise when recursive traversal encounters a cycle and does not record already-visited nodes. section 5.4.2 section 5.4.2
class ButtonWrapper implements Button {
private final Button delegate;
private boolean enabled;
ButtonWrapper(Button delegate) {
this.delegate = delegate;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public void onPressed() {
if (!enabled) return;
onPressed(); #1
}
}
Inspect the focused Java wrapper example and the unqualified recursive call that should have delegated to the wrapped object. section 5.4.2
Prevent infinite recursion by:
- Verifying that each recursive call can reach a valid exit condition and does not repeat the same relevant state. section 5.4.2
- Tracking previously visited nodes when traversing structures that may contain cycles; rewrite tail recursion with loops where appropriate. section 5.5
- Avoiding arbitrarily deep recursion and using heap-based structures such as ArrayDeque for non-tail recursion. section 5.5
