Rule S2447 requires methods returning Boolean to be explicitly annotated (e.g. @Nullable) if they may return null, on the grounds that callers might unbox the result directly (e.g. in an if statement) and risk a NullPointerException.
This rationale is technically correct, but it is applied inconsistently: the exact same risk exists for every other nullable wrapper type — Integer, Long, Double, etc. — when used in comparisons or arithmetic expressions, yet no equivalent rule flags those cases.
Concrete example
java
// Flagged by S2447
public Boolean isMinor() {
if (birthDate == null) {
return null; // age unknown — a legitimate third state
}
return age < 18;
}
java
// NOT flagged by any equivalent rule, same risk
public Integer getAge() {
if (birthDate == null) {
return null; // age unknown
}
return age;
}
Both methods can return null intentionally to represent “unknown” as a legitimate third state, distinct from true/false or from any specific number. Both expose callers to the exact same failure mode through auto-unboxing:
java
if (patient.isMinor()) { ... } // NPE risk
int age = patient.getAge(); // NPE risk
if (age > 18) { ... }
The underlying mechanism (auto-unboxing of a null wrapper) is identical in both cases. There is no technical justification for treating Boolean differently from Integer, Long, or Double in this respect.
Why this matters in practice
In domains where a tri-state boolean is a natural and correct modeling choice — for example, patient consent (granted / denied / not yet expressed) — this rule forces developers to either:
- add an external annotation dependency purely to satisfy the rule, or
- suppress the issue case-by-case, or
- disable the rule at the profile level,
for a pattern that is simply correct domain modeling, not a defect. Meanwhile, the equivalent (and equally risky) pattern with Integer/Long/Double raises no warning at all, so teams have no consistent guidance across wrapper types.
Request
Could the SonarSource team please clarify the reasoning behind singling out Boolean for this treatment? Specifically, we’d like to understand:
- Is there a technical reason
Booleanis treated differently from other nullable wrapper types with respect to unboxing risk? - If not, would the team consider either:
- extending equivalent detection to
Integer,Long,Double, etc. for consistency, or - relaxing/revising S2447 so it doesn’t require extra annotation overhead for legitimate tri-state
Booleanusage (e.g. by recognizing common null-check patterns before unboxing).
- extending equivalent detection to
We think the underlying principle (document nullable wrapper returns explicitly) is sound, but its asymmetric application to Boolean alone creates friction without a corresponding safety benefit relative to other wrapper types.
Thanks for considering this feedback.