6.1 Encapsulation
Encapsulation is the principle of bundling data fields and the methods that operate on that data into a single unit (the class), while deliberately restricting direct outside access to internal state.
In practice, encapsulation is implemented by declaring fields private and providing controlled public gateway methods (getters and setters). This allows validation, state integrity, and internal representation changes without breaking client code:
class Account {
private double balance; // hidden internal state
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount; // business rule validation
}
}
}
💡 Placement & Interview Deep-Dive
- How to create a Fully Immutable Class in Java?
- Declare the class as
finalso it cannot be subclassed. - Declare all fields as
privateandfinal. - Do NOT provide any setter methods.
- Initialize all fields through a parameterized constructor.
- Perform Defensive Copying when returning or receiving mutable objects (like
DateorList).
- Declare the class as
6.2 Inheritance
Inheritance allows a new class (subclass/child) to acquire the non-private properties and methods of an existing class (superclass/parent) using the extends keyword. It represents an "is-a" relationship:
class Animal {
void eat() { System.out.println("eating"); }
}
class Dog extends Animal {
void bark() { System.out.println("woof"); }
}
Dog d = new Dog();
d.eat(); // inherited from Animal
d.bark(); // defined in Dog
💡 Placement & Interview Deep-Dive
- Single Inheritance Constraint: Java supports single inheritance only for classes — a class can extend exactly one direct superclass. This avoids the infamous "Diamond Problem" of multiple inheritance found in C++. Multiple inheritance of type is supported through interfaces.
- What is the universal root superclass?
java.lang.Objectis the ultimate ancestor of every class in Java. If a class does not explicitly specify anextendsclause, the compiler silently insertsextends Object. - What does the
superkeyword do?super()invokes the parent class constructor (must be the first line in the child constructor).super.method()calls an overridden superclass method from within the subclass.
6.3 Polymorphism: Overloading vs Overriding
Polymorphism ("many forms") is the capability of a method to exhibit different behaviors based on context. Java implements polymorphism in two forms:
- Compile-Time Polymorphism (Method Overloading): Multiple methods in the same class sharing the same name but different parameters. Resolved by the compiler at compile-time.
- Runtime Polymorphism (Method Overriding): A subclass redefines a method inherited from its superclass with the exact same name, return type, and parameters. The JVM resolves which method to invoke dynamically at runtime based on the actual object on the heap, regardless of the reference type:
Animal a = new Dog(); // Superclass reference, Subclass object a.sound(); // Calls Dog's overridden sound() method at runtime!
💡 Placement & Interview Deep-Dive: The 5 Overriding Rules
- Signature Rule: Method name and parameter types must be identical.
- Covariant Return Type: The overriding method can return a subtype of the superclass method's return type.
- Access Modifier Rule: The overriding method cannot have a more restrictive access modifier (e.g. A
protectedmethod cannot be overridden asprivate; it can beprotectedorpublic). - Exception Handling Rule: The overriding method cannot throw broader or new checked exceptions than declared in the parent method. It can throw narrower subclasses, fewer checked exceptions, or any unchecked exceptions.
- What CANNOT be overridden?
privatemethods (not visible),staticmethods (method hiding, not overriding), andfinalmethods (cannot be changed).
6.4 Abstraction: Abstract Classes and Interfaces
Abstraction is the process of hiding implementation complexity and showing only essential feature interfaces to the user. Java provides two mechanisms for abstraction:
- Abstract Class (
abstract): A class that cannot be instantiated directly withnew. It can contain both concrete methods (with bodies) and abstract methods (without bodies):abstract class Shape { abstract double area(); // abstract method: subclasses must implement void display() { System.out.println("Shape rendered"); } // concrete method } - Interface (
interface): A contract specifying what a class must do, but not how. A class uses theimplementskeyword to implement an interface. A single class can implement multiple interfaces:interface Drawable { void draw(); // implicitly public abstract }
Reach for an abstract class when subclasses share common, reusable code as well as a contract. Reach for an interface when you need to define a contract across classes that may be otherwise unrelated, or when you need multiple inheritance of type.
💡 Placement & Interview Deep-Dive
- Modern Interface Features (Java 8 & 9+):
- Default Methods (Java 8+): Interfaces can provide concrete method implementations using the
defaultkeyword without breaking existing implementing classes. - Static Methods (Java 8+): Utility methods belonging to the interface itself.
- Private Methods (Java 9+): Internal helper methods shared between default methods.
- Default Methods (Java 8+): Interfaces can provide concrete method implementations using the
- Can an abstract class have a constructor? YES! Although an abstract class cannot be instantiated directly via
new AbstractClass(), its constructor runs when a concrete subclass is instantiated viasuper().