Field hiding & static method hiding in Java
Fields and static methods are not polymorphic.
p.tag says "P". p.getTag() says "C". Same object, same name, two different answers. Welcome to hiding.Only instance methods are polymorphic
Dynamic dispatch applies only to instance methods. Fields and static methods are picked by the declared type at compile time — the runtime object is never consulted.
Field vs method
What does this print?
class Parent {
String tag = "P";
String getTag() { return tag; }
}
class Child extends Parent {
String tag = "C";
String getTag() { return tag; }
}
Parent p = new Child();
System.out.println(p.tag + p.getTag());CCPCPPCP
Show the answer
PC. p.tag is a field access, resolved by the declared type Parent → "P". p.getTag() is an instance method, dispatched to Child → "C".
Two fields in one object
A field with the same name in a subclass doesn't replace the parent's — it hides it. A Child object contains both tag fields. Which one you see depends on the reference type; cast to see the other.
Parent p = new Child();
String t1 = p.tag; // "P"
String t2 = ((Child) p).tag; // "C"Static methods hide too
A static method with the same signature in a subclass hides the parent's. a.id() with A a = new B(); is compiled as A.id() — the object is irrelevant.
class A { static String id() { return "A"; } }
class B extends A {
static String id() { return "B"; }
}
A a = new B();
a.id(); // "A"Why no @Override on statics?
Why can't you put @Override on a static method that matches a parent's static method?
Think about it, then reveal the answer
Because there's nothing to override. Overriding means dynamic dispatch on an instance; static methods belong to classes. A same-signature static method only hides the parent's, so @Override is rejected.
Static vs instance clash
An instance method can't override a static one, and a static method can't hide an instance one. Mixing them with the same signature is a compile error.
class A { static void go() { } }
class B extends A {
void go() { } // compile error
}In real projects
Hidden fields are almost always accidents, which is why IDEs warn about them. Same for calling statics through instances (a.id()): linters flag it and recommend A.id(), so nobody believes it's polymorphic.
Key takeaways
- Fields are chosen by the declared type
- Static methods are chosen by the declared type
- Hiding is not overriding: no dynamic dispatch
- An instance method can't override a static one
A hiding field doesn't even need the same type: a subclass can declare int name that hides the parent's String name.
Practice questions
What does this print?
class A { String name = "A"; }
class B extends A { String name = "B"; }
void main() {
A a = new B();
System.out.println(a.name + ((B) a).name);
}- BB
- AB
- AA
- BA
Check your answer
AB. A B object contains both fields. Through an A reference you see A's name; after casting to B you see B's.
What does this print?
class A { static String id() { return "A"; } }
class B extends A {
static String id() { return "B"; }
}
void main() {
A a = new B();
System.out.println(a.id());
}- A
- B
- Compile error
Check your answer
A. Static methods are not dispatched on the object. a.id() is compiled as A.id() because a is declared as A.