Product: SonarQube Community Build 26.5.0.122743
sonar-java version: sonar-java 8.29 (build 43460)
sonar-java SE version: sonar-java-symbolic-execution 8.16.4 (build 1912)
Java source level: 21 (javac 21, source/target 21)
Rule
java:S1068 — Unused “private” fields should be removed
Description
S1068 flags private fields that are declared but never read. When such a field is declared inside a regular class, the rule correctly fires. When the exact same field declaration is moved into a record, S1068 stops firing — the rule appears to skip records entirely, even for declared static fields that are by definition not record components and therefore have the same unused-field semantics as in a plain class.
Reproducer
public class S1068ClassBefore {
private static final String DEFAULT = "x"; // BEFORE — S1068 fires (MAJOR).
private int x;
public S1068ClassBefore(int x) { this.x = x; }
public int getX() { return x; }
}
public record S1068RecordAfter(int x) {
private static final String DEFAULT = "x"; // AFTER — S1068 does NOT fire.
}
Expected behavior
A private static final field declared inside a record is not a record component (record components live in the header parentheses) and behaves like any other class-level private static final field with respect to reachability: if no code reads it, it is dead. S1068 should treat the field declaration uniformly across class and record declarations. It should raise on DEFAULT in both files.
Actual behavior
S1068ClassBefore:java:S1068(MAJOR) raised onDEFAULTwith message
“Remove this unused ‘DEFAULT’ private field.”S1068RecordAfter: no S1068 violation, even though the field has identical declaration, visibility, modifiers, and zero readers.