Static Fields Should Be Final
ID |
java.constant_fields_must_be_final |
Severity |
info |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
Java |
Tags |
code-style |
Description
Reports a static field that holds a constant — it is given a value where it is declared and never assigned again — but is not declared final.
A static field is not a constant just because it is static. A counter bumped on each call, a holder filled in lazily or from a static initializer, a field a framework assigns: none of these can take final, and telling their author to add it produces code that does not compile. So only fields initialized in their own declaration, with no later write recorded anywhere in the file — no assignment, no compound assignment, no ++ / -- — are reported. JUnit @Rule / @ClassRule fields are exempt: they are runner-managed test infrastructure, not constants.
Writes from another source file are invisible to the check, so a non-private static field assigned by a different class is still reported.
Rationale
A mutable static field is effectively global mutable state: it is shared across all instances and all threads. This makes the code harder to reason about, complicates testing, and is a frequent source of concurrency bugs. If the field is intended as a constant, declaring it static final communicates intent clearly and prevents accidental modification.
// Bad -- given a value here and never reassigned, but not final
static int MAX_RETRIES = 3;
static String DEFAULT_NAME = "admin";
// OK -- not constants: 'final' would not compile on any of these
private static int threadIndex = 0; // bumped on every call
private static Map<String, String> answers; // filled in from a static initializer
@ClassRule
public static LdapServer server = new LdapServer("/krb.ldif");
Remediation
Add the final modifier. If the field truly needs to be mutable at runtime (e.g. a counter or configuration flag), consider using an AtomicInteger, a volatile field, or a proper configuration mechanism instead of bare mutable statics.
// Good -- immutable constant
static final int MAX_RETRIES = 3;
static final String DEFAULT_NAME = "admin";