This rule flags cases where a derived class defines a static method with the same signature (name and parameters) as a static method in its base class.

Why is this an issue?

Method hiding occurs when a subclass defines a class-level method that has the same signature as a class-level method in its superclass. This is fundamentally different from method overriding, which applies to instance-level methods.

With instance-level methods, languages typically use polymorphism: the method called is determined by the actual runtime type of the object. This allows for dynamic behavior based on the object’s true type.

With class-level methods, however, languages use static binding: the method called is determined by the declared type of the reference at compile time, not the actual type of the object. This means that even if you have a superclass reference pointing to a subclass object, calling a class-level method will invoke the superclass version, not the subclass version.

This behavior is counterintuitive and contradicts developers' expectations based on how instance-level methods work. When reading code, developers naturally expect polymorphic behavior, but method hiding violates this expectation.

Consider this example pattern:

A parent class defines a class-level method that prints "Parent". A child class defines a class-level method with the same signature that prints "Child". When a variable is declared as the parent type but holds a child instance, calling the method through that variable prints "Parent", not "Child".

Even though the variable refers to a child instance, the parent’s method is called because the variable is declared as the parent type. This is confusing because instance-level methods would exhibit polymorphic behavior in the same situation.

The confusion is amplified when:

In Java, this looks like:

class Parent {
    static void display() {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    static void display() {  // Hides Parent.display()
        System.out.println("Child");
    }
}

Parent obj = new Child();
obj.display();  // Prints "Parent", not "Child"!

What is the potential impact?

Method hiding makes code harder to understand and maintain. Developers might incorrectly assume that method calls will be resolved at runtime based on the actual object type (dynamic dispatch), leading to logic errors that are difficult to diagnose. During refactoring, changing variable types can silently change which method is called, introducing subtle bugs. The code becomes less intuitive and requires deeper knowledge of compile-time method binding rules to understand correctly.

How to fix it

The simplest solution is to rename the static method in the subclass to avoid hiding. This makes the code’s intent clear and eliminates confusion about which method will be called.

Code examples

Noncompliant code example

class Parent {
    static void calculate() {
        // Parent implementation
    }
}

class Child extends Parent {
    static void calculate() {  // Noncompliant
        // Child implementation
    }
}

Compliant solution

class Parent {
    static void calculate() {
        // Parent implementation
    }
}

class Child extends Parent {
    static void calculateExtended() {
        // Child implementation
    }
}

Resources

Documentation

Standards

Related rules