05 - Understanding OOP in Java
A complete beginner-to-advanced guide to inheritance and polymorphism, aligned with the Oracle Certified Professional: Java SE 21 Developer (1Z0-830) exam objectives.
Table of Contents
- The Four Pillars of OOP
- Inheritance
- The
superKeyword - Method Overriding
- Overriding vs Overloading
- Polymorphism
- Field Hiding & Static Method Hiding
- Covariant Return Types
- Type Casting of Objects
- The
instanceofOperator - The
ObjectClass - Abstract Classes &
final - Certification Traps
- Common Mistakes
- Interview Questions
- Quick Revision Notes
- One-Page Cheat Sheet
1. The Four Pillars of OOP
| Pillar | Meaning | Java Mechanism |
|---|---|---|
| Encapsulation | Hide state, expose controlled access | private fields + getters/setters |
| Inheritance | Reuse via parent-child relationships | extends, implements |
| Polymorphism | One interface, many forms | Overriding, dynamic dispatch |
| Abstraction | Expose essentials, hide details | abstract classes, interfaces |
2. Inheritance
Inheritance lets a class (child/subclass) acquire fields and methods from another class (parent/superclass) using extends.
class Animal {
String name;
void eat() { System.out.println(name + " is eating"); }
}
class Dog extends Animal { // Dog inherits from Animal
void bark() { System.out.println(name + " says Woof"); }
}
Dog d = new Dog();
d.name = "Rex";
d.eat(); // inherited from Animal
d.bark(); // defined in Dog
Diagram: IS-A Relationship
Animal (superclass)
^
| extends (Dog IS-A Animal)
|
Dog (subclass)
Inheritance Rules
| Rule | Detail |
|---|---|
| Single inheritance (classes) | A class can extend only one class. |
| Multiple inheritance (interfaces) | A class can implement many interfaces. |
private members | Not inherited (not accessible in subclass). |
| Constructors | Not inherited (but super() calls them). |
Everything extends Object | Implicitly, if no other parent. |
final classes | Cannot be extended (e.g., String). |
Java does not support multiple inheritance of classes (to avoid the "diamond problem"), but it does for interfaces.
3. The super Keyword
super refers to the parent class. It accesses parent members or invokes the parent constructor.
class Vehicle {
int speed = 50;
void start() { System.out.println("Vehicle starting"); }
}
class Car extends Vehicle {
int speed = 100;
void show() {
System.out.println(speed); // 100 (this class)
System.out.println(super.speed); // 50 (parent)
}
@Override
void start() {
super.start(); // call parent version
System.out.println("Car starting");
}
}
Use of super | Purpose |
|---|---|
super.field | Access a hidden parent field. |
super.method() | Call the parent's (overridden) method. |
super(args) | Call the parent constructor (first statement). |
Implicit
super(): If a constructor doesn't callthis()orsuper(), the compiler inserts a no-argsuper()automatically.
4. Method Overriding
Overriding = a subclass provides a new implementation of a method inherited from its parent (same signature).
class Animal {
void sound() { System.out.println("Some sound"); }
}
class Cat extends Animal {
@Override
void sound() { System.out.println("Meow"); } // overrides
}
Animal a = new Cat();
a.sound(); // "Meow" — runtime type decides (dynamic dispatch)
Overriding Rules (Heavily Tested)
| Rule | Detail |
|---|---|
| Same signature | Same name + same parameters. |
| Return type | Same or covariant (subtype). |
| Access modifier | Same or more visible (cannot reduce). |
| Checked exceptions | Same, narrower, or none (cannot broaden). |
static methods | Cannot be overridden — they are hidden. |
final methods | Cannot be overridden. |
private methods | Not inherited → not overridden (redeclared as new). |
@Override | Optional annotation; compiler verifies the override. |
Access Modifier Trap
class Parent {
public void show() {}
}
class Child extends Parent {
// void show() {} // ERROR: cannot reduce visibility (public -> default)
public void show() {} // OK (same or wider)
}
Exception Trap
class Parent {
void m() throws IOException {}
}
class Child extends Parent {
// void m() throws Exception {} // ERROR: broader checked exception
void m() throws FileNotFoundException {} // OK: narrower
// void m() {} // OK: no exception
// void m() throws RuntimeException {} // OK: unchecked allowed
}
5. Overriding vs Overloading
| Feature | Overriding | Overloading |
|---|---|---|
| Where | Across parent & child | Same class (or inherited) |
| Signature | Same | Different parameters |
| Return type | Same or covariant | Can differ |
| Binding | Runtime (dynamic) | Compile-time (static) |
| Polymorphism | Runtime | Compile-time |
| Keyword | @Override (optional) | none |
class Calc {
int add(int a, int b) { return a + b; } // original
double add(double a, double b) { return a + b; } // OVERLOAD (diff params)
}
class SciCalc extends Calc {
@Override
int add(int a, int b) { return a + b + 1; } // OVERRIDE (same params)
}
6. Polymorphism
Polymorphism = "many forms." A parent reference can point to any subclass object, and the actual object's overridden method runs at runtime.
class Shape { double area() { return 0; } }
class Circle extends Shape {
double r;
Circle(double r) { this.r = r; }
@Override double area() { return Math.PI * r * r; }
}
class Square extends Shape {
double s;
Square(double s) { this.s = s; }
@Override double area() { return s * s; }
}
Shape[] shapes = { new Circle(2), new Square(3) };
for (Shape sh : shapes) {
System.out.println(sh.area()); // calls the correct override at runtime
}
Static vs Dynamic Binding
Reference type (compile time) -> decides what METHODS are VISIBLE
Object type (run time) -> decides which OVERRIDE is EXECUTED
Animal a = new Cat();
a.sound(); // Cat's version (object type wins for instance methods)
// a.purr(); // ERROR if purr() is only in Cat — reference type limits visibility
Key rule: For instance methods, the object decides which version runs. For fields and static methods, the reference type decides.
7. Field Hiding & Static Method Hiding
Unlike instance methods, fields and static methods are NOT polymorphic — they're resolved by the reference type, not the object.
Field Hiding
class Parent { int x = 10; }
class Child extends Parent { int x = 20; }
Parent p = new Child();
System.out.println(p.x); // 10 (reference type = Parent)
Child c = new Child();
System.out.println(c.x); // 20 (reference type = Child)
Static Method Hiding
class Parent { static void greet() { System.out.println("Parent"); } }
class Child extends Parent { static void greet() { System.out.println("Child"); } }
Parent p = new Child();
p.greet(); // "Parent" — static resolved by reference type, NOT object
| Member | Resolved By | Polymorphic? |
|---|---|---|
| Instance method | Object type (runtime) | ✅ Yes |
| Static method | Reference type (compile) | ❌ No (hidden) |
| Field | Reference type (compile) | ❌ No (hidden) |
This is one of the most common exam traps: only instance methods are polymorphic.
8. Covariant Return Types
An overriding method may return a subtype of the parent method's return type.
class Animal {
Animal reproduce() { return new Animal(); }
}
class Dog extends Animal {
@Override
Dog reproduce() { return new Dog(); } // covariant: Dog is a subtype of Animal
}
| Allowed return type change | |
|---|---|
| Same type | ✅ |
| Subtype (covariant) | ✅ (since Java 5) |
| Supertype | ❌ Compile error |
| Unrelated type | ❌ Compile error |
9. Type Casting of Objects
Upcasting (Always Safe, Implicit)
Dog d = new Dog();
Animal a = d; // upcast: Dog -> Animal (automatic)
Downcasting (Explicit, Risky)
Animal a = new Dog();
Dog d = (Dog) a; // downcast: must be explicit
d.bark();
ClassCastException Trap
Animal a = new Cat();
Dog d = (Dog) a; // compiles, but throws ClassCastException at RUNTIME
The cast compiles because Cat and Dog share the Animal type, but at runtime the object is a Cat, not a Dog.
Safe Downcasting with instanceof
Animal a = getAnimal();
if (a instanceof Dog) {
Dog d = (Dog) a; // safe
d.bark();
}
| Cast | Direction | Safety |
|---|---|---|
| Upcast | child → parent | Always safe (implicit) |
| Downcast | parent → child | Needs cast + runtime check |
| Unrelated types | — | Compile error |
10. The instanceof Operator
instanceof tests whether an object is an instance of a given type, returning a boolean.
Animal a = new Dog();
System.out.println(a instanceof Dog); // true
System.out.println(a instanceof Animal); // true
System.out.println(a instanceof Cat); // false
Pattern Matching for instanceof (Java 16+)
Combines the test and the cast into one step with a binding variable:
Object obj = "Hello";
// Old style
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}
// Modern style (Java 16+)
if (obj instanceof String s) { // 's' is auto-cast and in scope
System.out.println(s.length());
}
With Conditions & Scope
if (obj instanceof String s && s.length() > 3) {
System.out.println("Long string: " + s);
}
Rules & Traps
| Rule | Detail |
|---|---|
null instanceof X | Always false (no exception). |
| Compile check | x instanceof Y fails to compile if the types are unrelated. |
| Binding scope | The pattern variable is in scope only where the test is guaranteed true. |
&& extends scope | instanceof String s && s.isEmpty() is valid. |
String s = null;
System.out.println(s instanceof String); // false (null is never an instance)
11. The Object Class
Every class implicitly extends java.lang.Object — the root of all classes.
Key Methods
| Method | Purpose | Default Behavior |
|---|---|---|
equals(Object o) | Logical equality | Reference equality (==) |
hashCode() | Hash bucket | Identity-based int |
toString() | String form | ClassName@hexHash |
getClass() | Runtime type | Returns Class object |
clone() | Copy | Field-by-field (protected) |
wait/notify/notifyAll | Threading | Monitor coordination |
Overriding equals() and hashCode()
class Point {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Point p)) return false;
return x == p.x && y == p.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
The equals/hashCode Contract (Critical)
| Rule | Detail |
|---|---|
| Consistency | Equal objects must have equal hash codes. |
| Reverse not required | Equal hash codes do not imply equality. |
| Always override both | Overriding only one breaks HashMap/HashSet. |
equals is symmetric/transitive/reflexive | And consistent, and x.equals(null) is false. |
// Default toString
Object o = new Object();
System.out.println(o); // java.lang.Object@1b6d3586
Records (Java 16+) auto-generate
equals,hashCode, andtoStringcorrectly.
12. Abstract Classes & final
Abstract Classes
An abstract class cannot be instantiated and may contain abstract methods (no body) that subclasses must implement.
abstract class Shape {
abstract double area(); // no body — must be overridden
void describe() { // concrete method allowed
System.out.println("Area = " + area());
}
}
class Circle extends Shape {
double r;
Circle(double r) { this.r = r; }
@Override double area() { return Math.PI * r * r; }
}
| Rule | Detail |
|---|---|
| Cannot instantiate | new Shape() is illegal. |
| May have constructors | Called via super() from subclasses. |
| May mix abstract & concrete methods | |
| Subclass must implement all abstract methods | Or be abstract itself. |
abstract + final | Illegal combination. |
final Keyword
final on | Effect |
|---|---|
| Variable | Value can be assigned only once (constant). |
| Method | Cannot be overridden. |
| Class | Cannot be extended (e.g., String, Integer). |
final class Constants { } // no subclass allowed
class A {
final void lock() {} // no override allowed
final int MAX = 100; // constant
}
13. Certification Traps
| # | Trap |
|---|---|
| 1 | Java classes support single inheritance only; interfaces allow multiple. |
| 2 | Constructors and private members are not inherited. |
| 3 | Overriding can't reduce visibility or broaden checked exceptions. |
| 4 | static methods are hidden, not overridden (resolved by reference type). |
| 5 | Fields are resolved by reference type, not object (field hiding). |
| 6 | Only instance methods are polymorphic. |
| 7 | Covariant returns allow subtype returns; supertype/unrelated = error. |
| 8 | Downcasting compiles but can throw ClassCastException at runtime. |
| 9 | null instanceof X is always false (never throws). |
| 10 | instanceof between unrelated types is a compile error. |
| 11 | Overriding only equals() (not hashCode()) breaks hash collections. |
| 12 | super()/this() must be the first constructor statement. |
| 13 | abstract and final cannot be combined. |
| 14 | A subclass must implement all inherited abstract methods (or be abstract). |
| 15 | Pattern variable from instanceof is scoped only where the test is true. |
14. Common Mistakes
| Mistake | Fix |
|---|---|
Expecting static methods to be polymorphic | They are hidden; resolved by reference type. |
| Expecting fields to follow the object type | Fields use the reference type (hiding). |
Downcasting without instanceof | Check first to avoid ClassCastException. |
Overriding equals but not hashCode | Always override both. |
| Reducing visibility when overriding | Keep same or wider access. |
| Throwing broader checked exceptions in override | Throw same/narrower/none. |
Forgetting @Override | Add it so the compiler catches signature mistakes. |
| Trying to instantiate an abstract class | Subclass it and implement abstract methods. |
15. Interview Questions
Q1. What is inheritance and which keyword implements it?
A mechanism where a subclass acquires fields/methods from a superclass, using extends (classes) or implements (interfaces).
Q2. Why doesn't Java support multiple inheritance of classes? To avoid the diamond problem (ambiguity from two parents with the same member). Interfaces provide a safe alternative.
Q3. Difference between overriding and overloading? Overriding redefines a parent method with the same signature (runtime binding); overloading provides same-named methods with different parameters (compile-time binding).
Q4. What are the rules for method overriding? Same signature; same/covariant return; same or wider access; same/narrower/no checked exceptions; not static/final/private.
Q5. What is polymorphism? The ability of a parent reference to refer to subclass objects and invoke the correct overridden method at runtime.
Q6. How are static methods and fields resolved? By the reference type at compile time — they are hidden, not overridden, and are not polymorphic.
Q7. What is a covariant return type? An overriding method returning a subtype of the original return type.
Q8. What is the difference between upcasting and downcasting?
Upcasting (child→parent) is implicit and safe; downcasting (parent→child) is explicit and can throw ClassCastException.
Q9. What does null instanceof SomeType return?
false, always — without throwing an exception.
Q10. Explain the equals/hashCode contract. Equal objects must return equal hash codes; unequal hash codes imply non-equality; override both together for correct behavior in hash-based collections.
Q11. What is an abstract class? A class that can't be instantiated and may declare abstract methods that subclasses must implement.
Q12. What does final do on a class, method, and variable?
Class: can't be extended; method: can't be overridden; variable: can be assigned only once.
16. Quick Revision Notes
- Single class inheritance with
extends; multiple interface implementation. - Constructors and
privatemembers are not inherited. superaccesses parent members / constructor; implicitsuper()is auto-inserted.- Overriding: same signature, same/covariant return, same-or-wider access, same/narrower/no checked exceptions.
- Overriding = runtime binding; overloading = compile-time binding.
- Only instance methods are polymorphic.
- Fields and static methods are hidden — resolved by reference type.
- Covariant returns allow subtypes only.
- Upcast = implicit/safe; downcast = explicit, can throw
ClassCastException. - Guard downcasts with
instanceof; pattern matching binds + casts (Java 16+). null instanceof X→false; unrelatedinstanceof→ compile error.Objectis the root; overrideequals+hashCodetogether.- Abstract classes can't be instantiated;
abstract+finalis illegal. final: class (no extend), method (no override), variable (assign once).
17. One-Page Cheat Sheet
========================= OOP IN JAVA CHEAT SHEET =========================
INHERITANCE
class B extends A {} // single inheritance only
NOT inherited: constructors, private members
everything extends Object implicitly ; final class = no subclass
super
super.field | super.method() | super(args) (first stmt)
implicit super() inserted if no this()/super()
OVERRIDING (runtime, instance methods)
same signature ; return = same or COVARIANT (subtype)
access = same or WIDER (cannot reduce)
checked exceptions = same/NARROWER/none (cannot broaden)
cannot override: static (hidden), final, private
@Override -> compiler verifies
OVERLOADING (compile-time)
same name, different params ; return type alone NOT enough
POLYMORPHISM
Parent ref = new Child(); ref.method() -> CHILD's override
reference type = visible methods ; object type = which override runs
HIDING (NOT polymorphic)
fields -> resolved by REFERENCE type
static methods -> resolved by REFERENCE type
Parent p = new Child(); p.x and p.staticM() use Parent's
CASTING
upcast (child->parent): implicit, safe
downcast (parent->child): (Child) ref ; risky -> ClassCastException
guard with instanceof first
instanceof
obj instanceof Type -> boolean
null instanceof X -> false (no exception)
unrelated types -> compile error
PATTERN (16+): if (obj instanceof String s) { use s; }
if (obj instanceof String s && s.length()>3) {...}
Object CLASS
equals/hashCode/toString/getClass/clone/wait/notify
override equals + hashCode TOGETHER
equal objects -> equal hashCodes (reverse not required)
ABSTRACT / final
abstract class: no new, may have abstract+concrete methods, has ctors
subclass must implement all abstract methods (or be abstract)
abstract + final = ILLEGAL
final: class(no extend) method(no override) var(assign once)
===========================================================================
End of 05 - Understanding OOP in Java.