skip to content

What is the difference between method overriding and method hiding in Java?

level: middleimportance: must knowfreq 72%

answer

  1. Methods → runtime type (dynamic dispatch)
  2. Fields & statics → compile-time/declared type (static binding)
  3. Override = instance methods; Hide = static methods + fields
  4. @Override compiles only on a true override
  5. Same object can carry both Parent and Child fields at once

basics

~20 s

Overriding replaces an instance (non-static) method in a subclass; which version runs is decided at runtime by the object's actual type. Hiding happens with static methods (or fields): the subclass version masks the parent's, and which runs is decided at compile time by the declared type.

solid answer

~50 s

Overriding applies to instance methods: a subclass provides a new body for a method with the same signature, and the JVM uses dynamic dispatch so the object's runtime type picks the version, even through a supertype reference. Hiding applies to static methods and to fields: the subclass member with the same name shadows the parent's, but resolution is static (early) binding based on the reference's compile-time type, not the runtime object. So a static method called through a Parent reference runs Parent's version even if the object is a Child; an instance method runs Child's. The @Override annotation only compiles on true overrides, so it catches an accidental hide. Practically: never redeclare a static method with the same signature in a subclass, and avoid same-named fields in a hierarchy, because hiding is surprising and easy to misread as polymorphism.

go deeper

for a junior

Knows overriding replaces a method in a subclass and the @Override annotation exists. May not yet know static methods/fields behave differently.

for a middle

Can state the rule: instance methods dispatch by runtime type, statics and fields by declared type; explains the @Override safety net and predicts simple Parent p = new Child() outcomes.

for a senior

Explains the static-vs-dynamic-binding mechanism behind each, predicts field-hiding behavior including casts, and articulates why hiding is a code smell to avoid.

for a principal

Reasons about API/design implications: avoids same-named fields/statics in hierarchies, prefers overridable getters over protected fields, and recognizes how hiding can break Liskov-substitution expectations and library evolution.

## The core idea Java lets a subclass declare a member (method or field) with the same name as one in its superclass. Depending on *what kind* of member it is, Java does one of two very different things — **overriding** or **hiding** — and they resolve the call at different times. ### Terms defined - **Class / subclass (child) / superclass (parent):** a class can `extends` another, inheriting its members. `Child extends Parent`. - **Instance method:** a normal method that operates on an object (`void run()`), invoked on an instance. - **Static method:** a method declared `static`; it belongs to the *class itself*, not to any instance (`static void run()`). - **Field:** a data member (a variable) declared in the class body. - **Signature:** the method name plus its parameter types. Two methods *match* when their signatures are the same. - **Compile-time type (static type / declared type):** the type written in the variable's declaration, e.g. in `Parent p = new Child();` the compile-time type of `p` is `Parent`. - **Runtime type (dynamic type / actual type):** the class of the object actually created — here `Child`. - **Static binding (early binding):** the compiler decides at compile time *which* member a name refers to, using the compile-time type. - **Dynamic binding (late binding / dynamic dispatch):** the JVM decides at *run* time which method body to execute, using the runtime type of the object. This is what makes polymorphism work. ### Overriding (instance methods) When a subclass declares an instance method with the same signature as a superclass instance method, it **overrides** it. Java uses **dynamic dispatch**: the method body that runs is chosen by the object's **runtime type**, no matter what reference type you call through. ```java Parent p = new Child(); p.instanceMethod(); // runs Child's version — runtime type wins ``` This is the engine of polymorphism: you write code against `Parent` and get `Child`'s behavior. ### Hiding (static methods) Static methods are **not** polymorphic. If a subclass declares a static method with the same signature, it **hides** the parent's. Resolution is **static binding** by the **compile-time type** of the reference (and static methods should really be called on the class name, not a reference, anyway). ```java Parent p = new Child(); p.staticMethod(); // runs Parent's version — compile-time type wins ``` The object is a `Child`, but because the reference is declared `Parent` and the method is static, `Parent`'s version runs. This surprises people who expect override-like behavior. ### Field hiding Fields behave like static methods for resolution: they are **never** overridden, only **hidden**. Field access is resolved by the **compile-time type** of the expression. If both `Parent` and `Child` declare a field `name`, then `((Parent) child).name` reads `Parent.name` and `child.name` (typed `Child`) reads `Child.name` — *the same object holds both fields simultaneously.* ### The summary rule > **Methods resolve by the runtime type (dynamic). Fields and static methods resolve by the compile-time/declared type (static).** ### Why it matters Hiding looks like overriding in source code but behaves oppositely, which produces bugs that are hard to spot. The `@Override` annotation is your guard: it compiles only on a genuine override and errors on an accidental hide or signature typo. Best practice: don't redeclare static methods across a hierarchy, and keep field names unique down a hierarchy (or keep fields private and expose them through overridable getters, which *do* dispatch dynamically).

  • How does @Override help you distinguish the two?
    @Override compiles only when the method genuinely overrides a superclass instance method. If you accidentally write a static method, mismatch the signature, or try to 'override' a field, the compiler rejects it — turning a silent hiding/typo bug into a compile error.
  • Can a subclass field and a superclass field of the same name coexist on one object?
    Yes. Hiding doesn't replace the parent field; both exist in the object simultaneously. Which one you read depends on the compile-time type of the reference expression you use to access it.

saying these in an interview costs you the question

  • Claiming static methods can be overridden polymorphically
  • Thinking fields are polymorphic / resolved by runtime type
  • Believing @Override works on static methods
  • Saying hiding and overriding are just two names for the same thing

context