Almost everyone can recite "the four pillars of OOP". Almost everyone freezes when an interviewer turns them into code: a subclass object is held in a superclass reference, and you must decide which method or field is used.
Three things decide that answer: the reference type, the object type, and the moment the binding happens. Separate them and the pillars stop being slogans, and interview output questions become predictable.
The four OOP pillars in one screen
Encapsulation: private fields plus controlled getters, setters or behaviour methods protect an object's valid state.
Inheritance:
extendscreates a subclass that receives accessible members from a superclass and can specialise its behaviour.Abstraction: an abstract class or interface presents the operations a caller needs while hiding implementation detail.
Polymorphism: method overriding and dynamic dispatch let one reference type produce behaviour chosen by the runtime object.
Interviewers test the interaction, not just four separate definitions. Inheritance establishes the type relationship, abstraction supplies the contract, encapsulation protects each object's state, and polymorphism decides which implementation answers a call. For a subject-level view outside placement interviews, OOP for CS teaching exams reinforces the same foundations.
Inheritance and reference versus object type
A superclass reference can hold a subclass object. This safe conversion is upcasting:
A obj = new B();The reference variable obj has declared type A, while the object created in the heap has actual type B. The compiler uses the declared type to check which members may be accessed. At runtime, Java can use the actual object type to choose an overridden instance method.
That creates the two questions behind many Java interviews:
Which overridden method runs?
Which field is read?
They do not have the same rule.
Worked example: dynamic method dispatch and compile-time field access
Start from this program:
class A {
int x = 10;
void show() { System.out.println("A"); }
}
class B extends A {
int x = 20;
void show() { System.out.println("B"); }
}
public class Main {
public static void main(String[] args) {
A obj = new B();
obj.show();
System.out.println(obj.x);
}
}Trace it without guessing:
objis DECLARED typeAbut POINTS TO aBobject.Methods are dispatched on the actual runtime object type:
obj.show()runsB.show()and printsB.Fields are NOT polymorphic; they are resolved by the reference (compile-time) type
A:obj.xreadsA.x = 10.Output, two lines:
Bthen10.
B
10The B object contains the inherited A part as well as the field declared by B. The repeated field name is hidden, not dynamically overridden. Casting the reference can change which field expression the compiler selects, but the object's runtime type already controls the overridden show() call.

Overloading versus overriding
Overloading uses the same method name with a different parameter list. The compiler selects the signature from the available methods and argument types:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }add(2, 3) selects add(int, int) and returns 5. add(2.0, 3.0) selects add(double, double) and returns 5.0. This is compile-time binding.
Overriding occurs when a subclass supplies the same instance-method signature as its superclass. In the worked example, B.show() overrides A.show(), and the runtime object selects it. This is runtime binding.
Use @Override whenever you intend to override. If you accidentally change the parameter list or misspell the method, the compiler reports the mismatch instead of quietly creating an overload.

Abstraction and encapsulation as design
An abstract class is useful when closely related subclasses share state, constructors and partial implementation. An interface is useful when you need a capability contract across otherwise unrelated classes. A Java class extends one class but can implement several interfaces.
An interface is not merely an old-style container for abstract methods. Java 8+ interfaces can provide default methods, which let a contract evolve with reusable behaviour. The Java 8 to Java 21 interview features guide follows this language evolution beyond the OOP foundation.
Encapsulation is more than making every field private and generating setters. A BankAccount should expose deposit(amount) that rejects invalid amounts, not a public setBalance() that permits any state. Good encapsulation exposes behaviour and keeps the invariant inside the class that owns it.
Both pillars sit in one type:
abstract class Account {
private double balance;
void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("deposit must be positive");
balance += amount;
}
double balance() { return balance; }
abstract double interestFor(int months);
}
class FixedDeposit extends Account {
double interestFor(int months) { return balance() * 0.06 * months / 12; }
}balance is private, so nothing outside the class can drive it negative; deposit owns that invariant. interestFor is declared but not implemented in Account, so the rate rule belongs to each concrete account type. Deposit 100000 into a FixedDeposit and interestFor(6) evaluates to 3000.0. A caller holding only an Account reference gets that number through dynamic dispatch, without ever seeing the formula or the balance.
Follow-ups interviewers actually ask
Can a static method be overridden? No. A subclass can declare a static method with the same signature, but that is method hiding and is resolved using the reference or class at compile time.
What does final do? A final instance method cannot be overridden. A final class cannot be subclassed. A final variable cannot be reassigned after its permitted initialisation.
Can a constructor be overridden? No. Constructors are not inherited. A subclass constructor can call a superclass constructor with super(...), but it does not replace it polymorphically.
What are upcasting and downcasting? Upcasting a B object to an A reference is safe. Downcasting asks Java to treat an A reference as B; it throws ClassCastException if the actual object is not a B. Check with instanceof when the design genuinely requires a downcast.
Do private methods participate in overriding? No. They are not inherited as visible subclass methods, so a same-named subclass method is a separate declaration.
Those five follow-ups are the OOP slice of a fresher round. Strings, collections and exception handling get the same treatment in Java interview questions for freshers.
How this shows up, short version and next step
An interview usually starts with the four definitions, then moves to overloading versus overriding and finally to a short output trace. Say the binding rule before the answer: the reference type picks fields at compile time, while the object type picks overridden instance methods at runtime.
KnowledgeGate's question bank carries more than 1,200 programming-language questions on overriding, overloading and runtime-dispatch output. Work those behaviours in the Complete Java course, then use the Coding Skills catalogue to extend them into implementation practice. If you can explain why the example prints B and then 10, the four pillars are becoming usable knowledge.




