Accessor Uses The Wrong Field

ID

java.accessor_uses_expected_field

Severity

high

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

Java

Tags

code_smell, copy-paste, field

Description

Reports a getter (getX/isX, no parameters, non-void) whose single return statement does not reference the field named x, or a setter (setX, one parameter, void) whose single assignment statement does not write the field named x — while a field named x, of the accessor’s own type, exists in the type.

Rationale

A pair of accessors is often written by copying the first one and renaming it, and the field reference inside the body is left behind. The code compiles and type-checks: the method returns, or assigns, a real field of the right type, so nothing about it looks broken.

public class Money {
  private long cents;
  private String currency;

  public String getCurrency() {
    return currency;
  }

  public long getCents() {
    return currency.length();   // wrong field: 'cents' is never read
  }

  public void setCurrency(String value) {
    this.cents = 0;              // wrong field: 'currency' is never written
  }
}

Several conditions keep the rule quiet on legitimate code:

  • a field named after the accessor must actually exist — an accessor for a name with no matching field is a computed property, not a mistake;

  • the body must be exactly one statement. A longer body may validate, convert or derive the value without directly touching the field, and telling that apart from a real mistake needs more than syntax, so it is left alone rather than guessed at. This is narrower than a full-body scan: a copy-paste mistake hiding inside a multi-statement accessor is not reported by this rule;

  • the field must hold what the accessor returns or takes (compared by simple type name, with a primitive and its wrapper counting as one type). boolean isEmpty() beside a sentinel Node empty, or Jid getService() beside an XmppConnectionService service, is not a mistaken accessor — returning that field would not even compile. A getter that widens (List<T> getChildren() over an ArrayList<T> children) is left alone as a consequence;

  • a static accessor is never asked to read an instance field;

  • a getter that produces the field’s value is a factory, not an accessor. When the field’s own initializer, or an assignment to it anywhere in the type, calls the getter, the data flows field ← method and nothing is wrong;

  • the field may be read one hop away — through another method of the same type (the JavaFX xProperty().get() convention, an overload, a one-line conversion), or through a second field that is initialized from it (a cached Collections.unmodifiableList(children) view).

When both a boolean isX field and an unrelated X x field exist, the exactly-named one wins: boolean isStaff() { return this.isStaff; } is a correct accessor even next to a Staff staff association.

The expected field name is derived from the accessor name by removing the get/is/set prefix and folding case on the first character only: getURL expects a field named URL, not url — every character after the first must match exactly. A field spelled differently (a leading underscore, an all-lowercase acronym) is not recognised as corresponding to the accessor and the accessor is left alone.

Remediation

Fix the field reference to match the accessor’s own name.

public class Money {
  private long cents;
  private String currency;

  public long getCents() {
    return cents;
  }

  public void setCurrency(String value) {
    this.currency = value;
  }
}

© 2026 Xygeni. All rights reserved