Method That Cannot Be An Override

ID

java.child_method_not_an_override

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Code Smell

Language

Java

Tags

code-smell, inheritance

Description

Reports a subclass method that shares its name and parameter types with a method of its direct parent, where exactly one of the two is static. Java resolves a static method by the reference’s declared type and never by dynamic dispatch, so a static method and an instance method can never override one another however alike their signatures look. The author believes the subclass now controls what runs; the parent’s original method keeps running for every caller that holds a reference typed as the parent.

The pair only reaches this rule when the parent’s method is not inherited by the subclass — otherwise javac rejects the mismatch outright (JLS 8.4.8.1 and 8.4.8.2: an instance method cannot override a static one, and a static method cannot hide an instance one). The shape that compiles, and the one this rule is about, is a parent method the subclass cannot inherit because it is not accessible from there — package-private, with the subclass in a different package.

Rationale

// ---- com/acme/io/Connection.java -------------------------------------------------------------
package com.acme.io;

public class Connection {

  static void open() {                 // package-private: a static factory-style helper
    // ...
  }
}
// ---- com/acme/pool/PooledConnection.java -----------------------------------------------------
package com.acme.pool;

import com.acme.io.Connection;

public class PooledConnection extends Connection {

  public void open() {                 // FLAW — looks like it replaces the parent's open()
    // ...
  }
}

Connection.open() and PooledConnection.open() are two unrelated methods that happen to share a name. The subclass is in a different package, so the parent’s package-private open() is not inherited and the declaration compiles. Any code inside com.acme.io that calls open() runs the parent’s version, never the subclass’s, regardless of which concrete type the reference points to.

Remediation

If an override was genuinely intended, fix the mismatch: match the parent’s static modifier, and widen the parent’s method so the subclass can actually inherit it. If the two methods are meant to be unrelated, rename the subclass’s method so nothing suggests a relationship that does not exist.

public class PooledConnection extends Connection {

  public static void open() {          // matches the parent's modifier: hides it, as intended
    // ...
  }
}

Limitations

The parent class is declared in another file, so this rule resolves it through the project-wide software model. When the model has no entry for the parent, or the parent’s method table has no method with the same name and the same parameter types, the rule stays silent. Only the direct parent is examined — a method inherited from a grandparent is out of scope. A method annotated @Override is never reported: it is an intended override, and the compiler already rejects a broken one. A private parent method is never reported either: it is invisible from the subclass, so no call can dispatch to the wrong one of the two and there is nothing to fix.

Upstream also flags a same-name, same-arity method whose parameter types resolve to a different package than the parent’s (the classic "wrong import" mistake); this rule does not attempt that comparison and treats it as a documented false negative rather than a guess.

© 2026 Xygeni. All rights reserved