MindIQ Academy

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

  1. The Four Pillars of OOP
  2. Inheritance
  3. The super Keyword
  4. Method Overriding
  5. Overriding vs Overloading
  6. Polymorphism
  7. Field Hiding & Static Method Hiding
  8. Covariant Return Types
  9. Type Casting of Objects
  10. The instanceof Operator
  11. The Object Class
  12. Abstract Classes & final
  13. Certification Traps
  14. Common Mistakes
  15. Interview Questions
  16. Quick Revision Notes
  17. One-Page Cheat Sheet

1. The Four Pillars of OOP

PillarMeaningJava Mechanism
EncapsulationHide state, expose controlled accessprivate fields + getters/setters
InheritanceReuse via parent-child relationshipsextends, implements
PolymorphismOne interface, many formsOverriding, dynamic dispatch
AbstractionExpose essentials, hide detailsabstract 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

RuleDetail
Single inheritance (classes)A class can extend only one class.
Multiple inheritance (interfaces)A class can implement many interfaces.
private membersNot inherited (not accessible in subclass).
ConstructorsNot inherited (but super() calls them).
Everything extends ObjectImplicitly, if no other parent.
final classesCannot 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 superPurpose
super.fieldAccess 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 call this() or super(), the compiler inserts a no-arg super() 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)

RuleDetail
Same signatureSame name + same parameters.
Return typeSame or covariant (subtype).
Access modifierSame or more visible (cannot reduce).
Checked exceptionsSame, narrower, or none (cannot broaden).
static methodsCannot be overridden — they are hidden.
final methodsCannot be overridden.
private methodsNot inherited → not overridden (redeclared as new).
@OverrideOptional 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

FeatureOverridingOverloading
WhereAcross parent & childSame class (or inherited)
SignatureSameDifferent parameters
Return typeSame or covariantCan differ
BindingRuntime (dynamic)Compile-time (static)
PolymorphismRuntimeCompile-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
MemberResolved ByPolymorphic?
Instance methodObject type (runtime)✅ Yes
Static methodReference type (compile)❌ No (hidden)
FieldReference 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();
}
CastDirectionSafety
Upcastchild → parentAlways safe (implicit)
Downcastparent → childNeeds cast + runtime check
Unrelated typesCompile 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

RuleDetail
null instanceof XAlways false (no exception).
Compile checkx instanceof Y fails to compile if the types are unrelated.
Binding scopeThe pattern variable is in scope only where the test is guaranteed true.
&& extends scopeinstanceof 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

MethodPurposeDefault Behavior
equals(Object o)Logical equalityReference equality (==)
hashCode()Hash bucketIdentity-based int
toString()String formClassName@hexHash
getClass()Runtime typeReturns Class object
clone()CopyField-by-field (protected)
wait/notify/notifyAllThreadingMonitor 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)

RuleDetail
ConsistencyEqual objects must have equal hash codes.
Reverse not requiredEqual hash codes do not imply equality.
Always override bothOverriding only one breaks HashMap/HashSet.
equals is symmetric/transitive/reflexiveAnd 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, and toString correctly.


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; }
}
RuleDetail
Cannot instantiatenew Shape() is illegal.
May have constructorsCalled via super() from subclasses.
May mix abstract & concrete methods
Subclass must implement all abstract methodsOr be abstract itself.
abstract + finalIllegal combination.

final Keyword

final onEffect
VariableValue can be assigned only once (constant).
MethodCannot be overridden.
ClassCannot 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
1Java classes support single inheritance only; interfaces allow multiple.
2Constructors and private members are not inherited.
3Overriding can't reduce visibility or broaden checked exceptions.
4static methods are hidden, not overridden (resolved by reference type).
5Fields are resolved by reference type, not object (field hiding).
6Only instance methods are polymorphic.
7Covariant returns allow subtype returns; supertype/unrelated = error.
8Downcasting compiles but can throw ClassCastException at runtime.
9null instanceof X is always false (never throws).
10instanceof between unrelated types is a compile error.
11Overriding only equals() (not hashCode()) breaks hash collections.
12super()/this() must be the first constructor statement.
13abstract and final cannot be combined.
14A subclass must implement all inherited abstract methods (or be abstract).
15Pattern variable from instanceof is scoped only where the test is true.

14. Common Mistakes

MistakeFix
Expecting static methods to be polymorphicThey are hidden; resolved by reference type.
Expecting fields to follow the object typeFields use the reference type (hiding).
Downcasting without instanceofCheck first to avoid ClassCastException.
Overriding equals but not hashCodeAlways override both.
Reducing visibility when overridingKeep same or wider access.
Throwing broader checked exceptions in overrideThrow same/narrower/none.
Forgetting @OverrideAdd it so the compiler catches signature mistakes.
Trying to instantiate an abstract classSubclass 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 private members are not inherited.
  • super accesses parent members / constructor; implicit super() 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 Xfalse; unrelated instanceof → compile error.
  • Object is the root; override equals + hashCode together.
  • Abstract classes can't be instantiated; abstract + final is 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.