Else-If Chain Missing Final Else

ID

java.else_if_without_else

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Code Smell

Language

Java

Tags

code-style, conditional, control-flow

Description

Disabled by default. No syntactic signal separates an intended decision table from a guard chain, so a review of real projects found almost no actionable report: dispatch chains where no match is a deliberate no-op, and chains whose trailing return/throw already acts as the final else, are indistinguishable from a genuine omission. The usual escape hatch does not help either, because a comment explaining the omission is only honoured inside an empty else block and these chains have no else at all.

Reports an if / else if chain that does not end with a plain else. A lone if, and a plain if / else with no else if, are out of scope — the chain must contain at least one else if to be reported, and it is reported once regardless of how many else if branches it has.

A final else block that has no statements is treated the same as a missing one, unless it holds a comment explaining why no action is taken.

Rationale

Once a condition is spelled out more than once, the chain reads as a decision table, and a reader takes the absence of a final else to mean the listed branches cover every input. When they do not, the method falls through silently with whatever state it already had — exactly the input nobody wrote a test for. A final else, even one that only documents the assumption, makes that coverage explicit.

if (status == 0) {
  markPending();
} else if (status == 1) {
  markActive();
}

Remediation

Add a final else that either handles the remaining case or documents why none is expected.

if (status == 0) {
  markPending();
} else if (status == 1) {
  markActive();
} else {
  throw new IllegalStateException("Unknown status: " + status);
}

© 2026 Xygeni. All rights reserved