Back to Blog
Java

Java Overriding vs Hiding: Key Differences

java overriding vs hiding: Understand the difference between overriding and hiding in Java: instance methods, static methods, and field hiding with code examples and p...

method overridingmethod hidingstatic methodsfield hidingJava OOP
Illustration contrasting method overriding with dynamic dispatch and method hiding with compile-time binding in Java.

When you declare a method in a subclass with the same signature as a method in its superclass, the behavior depends on whether the method is an instance method or a static method. This is the core of java overriding vs hiding. Instance methods are overridden; static methods are hidden. The distinction affects which method is called, how the call is resolved, and what the compiler allows. Getting this wrong leads to subtle bugs that are hard to trace because the code compiles and runs, but does not do what the developer intended.

What Is Method Overriding?

Method overriding occurs when a subclass declares an instance method with the same signature and return type (or a covariant return type) as an instance method in its superclass. The subclass method replaces the superclass method in the inheritance chain. When you call the method on an object whose runtime type is the subclass, the subclass version runs, regardless of the reference type used for the call.

class Animal { public void speak() { System.out.println("Animal speaks"); } } class Dog extends Animal { @Override public void speak() { System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal a = new Dog(); a.speak(); // prints "Dog barks" } }

The @Override annotation is optional but recommended. It tells the compiler to check that a superclass method with the same signature actually exists. If you mistype the signature, the compiler will report an error instead of silently creating a new method. Overriding is the foundation of polymorphism in Java. The JVM uses dynamic dispatch to select the method implementation based on the runtime type of the receiver object.

What Is Method Hiding?

Static methods belong to the class, not to instances. When a subclass declares a static method with the same signature as a static method in its superclass, the subclass method hides the superclass method. Hiding means that the method to call is determined at compile time based on the reference type, not the runtime type of the object.

class Parent { public static void whoAmI() { System.out.println("Parent"); } } class Child extends Parent { public static void whoAmI() { System.out.println("Child"); } } public class Main { public static void main(String[] args) { Parent p = new Child(); p.whoAmI(); // prints "Parent" because reference type is Parent Child c = new Child(); c.whoAmI(); // prints "Child" because reference type is Child } }

Even though p points to a Child instance, the call p.whoAmI() resolves to Parent.whoAmI() because static method calls are bound at compile time. The compiler uses the declared type of the variable. This is why static methods cannot be overridden; they are hidden. The @Override annotation is not allowed on a static method that hides a superclass static method. Attempting to use it causes a compilation error.

Field Hiding: Variables Behave Differently

Fields are also subject to hiding, but the rules are slightly different. If a subclass declares a field with the same name as a field in its superclass, the subclass field hides the superclass field. This applies to both instance fields and static fields. Access to the field is determined by the reference type, similar to static method hiding, but with an important nuance: field access is never polymorphic.

class Base { int value = 10; } class Derived extends Base { int value = 20; } public class Main { public static void main(String[] args) { Base b = new Derived(); System.out.println(b.value); // prints 10 Derived d = new Derived(); System.out.println(d.value); // prints 20 } }

The object is the same, but b.value accesses Base.value because the reference type is Base. Field hiding is generally discouraged because it leads to confusing code. There is no @Override equivalent for fields. The compiler does not warn you that you are hiding a field unless you enable specific linting options.

Key Differences Between Overriding and Hiding

The following table summarizes the main differences. Use it as a quick reference when you are deciding whether a method will be overridden or hidden.

AspectOverridingHiding
Applies toInstance methodsStatic methods and fields
ResolutionRuntime (dynamic dispatch)Compile time (reference type)
@Override allowedYesNo (for methods)
PolymorphismYesNo
Call depends onRuntime type of objectDeclared type of variable
Covariant return typesAllowedNot allowed for static methods
Access modifierCannot reduce visibilityCannot reduce visibility (for methods)

For methods, both overriding and hiding require the access modifier to be at least as accessible as the method in the superclass. For example, a public method in the superclass cannot be overridden or hidden by a protected method in the subclass. The compiler enforces this rule.

Common Pitfalls and Misunderstandings

One frequent mistake is calling a static method through an instance reference. The code compiles, but the behavior may surprise you because the compiler uses the reference type, not the object's runtime type.

class A { static void print() { System.out.println("A"); } } class B extends A { static void print() { System.out.println("B"); } } public class Main { public static void main(String[] args) { A a = new B(); a.print(); // prints "A" B b = new B(); b.print(); // prints "B" } }

Many developers expect a.print() to print "B" because a refers to a B instance. That expectation is wrong for static methods. The Java compiler generates a call to A.print() because the static type of a is A. Modern IDEs often warn about this pattern, but the code still compiles. Avoid calling static methods through instances; use the class name instead.

Another pitfall is accidentally hiding a method when you intended to override it. If you forget the static keyword in the subclass method while the superclass method is static, you will get a compilation error. Conversely, if you add static to a method that should override an instance method, the compiler rejects it because you cannot override an instance method with a static method. The compiler is strict here, which is helpful.

Design and Maintainability Considerations

Prefer overriding over hiding when you need polymorphic behavior. Overriding aligns with the object-oriented principle that subclasses refine or extend the behavior of their superclass. Hiding static methods is sometimes necessary when a subclass wants to provide its own version of a utility method, but it can confuse callers because the method called depends on the reference type. If you find yourself hiding a static method, consider whether the method should be static at all. Often, an instance method would be more appropriate and would allow overriding.

Field hiding is almost always a design smell. If a subclass declares a field with the same name as a superclass field, it is easy to accidentally access the wrong one, especially when the field is used inside methods inherited from the superclass. The superclass methods access the superclass field, while the subclass methods access the subclass field, leading to inconsistent state. Use different names or make fields private and use getters/setters to avoid this problem.

Final Technical Consideration: Covariant Return Types and Final Methods

When overriding an instance method, you may use a covariant return type, meaning the return type can be a subclass of the superclass method's return type. This is not allowed for static method hiding; the return type must be identical. Also, a method declared final in the superclass cannot be overridden or hidden. The compiler will reject any attempt to do so. This is a deliberate language design choice to prevent subclasses from changing behavior that the superclass author intended to be fixed.

Understanding java overriding vs hiding is essential for writing predictable Java code. Overriding gives you runtime polymorphism; hiding gives you compile-time method selection. Use each intentionally, and be aware of the reference type when calling static methods or accessing fields. The rules are strict, and the compiler enforces them, but the semantics can still surprise developers who expect everything to behave like overriding.

java overriding vs hiding: Practical Usage and Code Examples | RYUSLOG DEV