Method Clashing With A Field Name

ID

java.method_name_matches_field

Severity

critical

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

Java

Tags

code-style, naming

Description

Reports a method whose name is the same as a field of the same type, or differs from it only in capitalization.

Fields and methods declared directly in the type are compared; record components count as fields. Inherited members are not considered.

Capitalization is folded for ordinary fields only. A constant is compared by its exact name: SCREAMING_SNAKE for constants and camelCase for methods are two conventions being followed, so static Version zero() returning static final Version ZERO is not a clash.

Rationale

The pair is read wrong by everyone who comes after. At the call site ferry.route and ferry.route() look like the same thing, and a Route / route pair looks like a typo that the compiler happily accepts. A method name is supposed to name an action and therefore contain a verb, which a field name almost never does — so the clash is usually a naming slip rather than a deliberate design.

public class Ferry {
  public String route;
  private int berth;

  public void route() {          // clashes with the field
    ...
  }

  public void Berth(int slot) {  // differs from the 'berth' field only in case
    ...
  }
}

The following are intentional idioms and are not reported. All of them require the method name to match the field name exactly — a pair that differs in capitalization is always reported, because two spellings of one name is the defect itself.

  • an accessor — a zero-argument, non-void method whose name is exactly the field name (name() returning name);

  • a mutator of the same field, whatever it returns — the builder idiom. The return type is no guide to it: a nested builder returns Outer.Builder, a generic one returns its self-type T, and plenty of mutators are plain void. What is checked is that the method takes a parameter and its body writes that field, however it gets there: after a guard, from inside a switch, alongside a companion field, through the object the field holds (this.enabled.set(v) against a BooleanProperty), or by delegating to another overload of the same name (ids(String…​ v) { return ids(List.of(v)); });

  • a static method clashing with an instance field. The two are never reached through the same expression — a call site reads CellSpec.text(…) or spec.text, never both — and such a pair is almost always the named static factory of a value type, named after the field it fills in. A static method clashing with a static field is reported;

  • a method annotated @Override, because its name comes from the supertype;

  • a pair where both members are private, which cannot confuse anyone outside the type.

public final class Options {
  private final BooleanProperty verbose = new SimpleBooleanProperty();
  private List<String> tags;

  public void verbose(boolean verbose) {           // not reported: writes through the property
    this.verbose.set(verbose);
  }

  public Options tags(List<String> tags) {         // not reported: a guard before the write
    if (tags.isEmpty()) {
      throw new IllegalArgumentException("empty");
    }
    this.tags = List.copyOf(tags);
    return this;
  }

  public Options tags(String... tags) {            // not reported: delegates to the overload above
    return tags(List.of(tags));
  }
}

A zero-argument action that flips a same-named flag is not a mutator and is still reported — void shutdown() setting shutdown = true stores nothing the caller passed, and obj.shutdown versus obj.shutdown() is exactly the pair a reader trips over.

Remediation

Rename the member. Renaming a public method can break callers, so prefer renaming the field — and while you are there, give the method a verb.

public class Ferry {
  public String routeName;
  private int berthNumber;

  public void sail() {
    ...
  }

  public void assignBerth(int slot) {
    ...
  }
}

If the method really is an accessor or a mutator for the field, give it the exact field name — a zero-argument accessor, or a mutator that takes the value and writes that field — and the pair is accepted as the getter / builder idiom.

© 2026 Xygeni. All rights reserved