Invalid Math.clamp Range
ID |
java.math_clamp_invalid_range |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Code Smell |
Language |
Java |
Tags |
arithmetic, code-style |
Description
Reports a Math.clamp(value, min, max) call whose three arguments cannot possibly do what
clamp is for:
-
minandmaxare the same literal or the same symbol — the call always returns that one fixed value; -
valueandmin, orvalueandmax, are the same literal or the same symbol — clamping a value against itself is pointless; -
minandmaxare both numeric literals andminis greater thanmax— an inverted range.
Rationale
Math.clamp, added in Java 21, fits a value inside [min, max] in one call instead of the
older Math.min(max, Math.max(value, min)) combination. If min is greater than max, the
range is invalid and clamp throws IllegalArgumentException at the call site, every single
time — a mistake most often caused by the two bounds being written in the wrong order.
Math.clamp(red, 255, 0); // throws IllegalArgumentException: min (255) > max (0)
Math.clamp(red, 5, 5); // always returns 5 -- min and max are the same
Math.clamp(red, red, 255); // pointless -- use Math.min(red, 255)
Only literal and simple-symbol arguments are decidable from a single call. A computed
argument (a + b, a nested call, a cast) is not evaluated and the rule stays silent on it
rather than guessing. Symbol equality is by name within the call’s own arguments — no
aliasing analysis, so two different variables that happen to hold equal values at runtime are
not treated as equal.
Remediation
Put the bounds in the right order, or replace the call with the single-bound method that says what is actually meant.
Math.clamp(red, 0, 255);
Math.min(red, 255); // was: Math.clamp(red, red, 255)
Math.max(0, red); // was: Math.clamp(red, 0, red)