☕ Java

Interfaces in Java

Interfaces define a contract: 'if you claim to be X, you must be able to do Y and Z.' They're how Java achieves flexible, loosely coupled design — and since Java 8, they've become even more powerful.

Interface vs Abstract Class — When to Use Which

This comes up in interviews constantly. Here's the practical breakdown: | Feature | Interface | Abstract Class | |----------------------|--------------------------------|---------------------------------| | Methods | abstract by default | can be abstract OR concrete | | Variables | public static final only | any type (instance vars allowed)| | Inheritance | implements (multiple allowed) | extends (single only) | | Constructor | No | Yes | | Best for | Defining a capability/contract | Sharing common implementation | Rule of thumb: If you're defining WHAT something can do (capability) → interface. If you're defining a SHARED BASE with some shared code → abstract class. Real examples: • Comparable, Runnable, Serializable in Java's own library → all interfaces (capabilities) • AbstractList, AbstractMap in Collections → abstract classes (shared implementation)

Default Methods (Java 8+) — Backwards-Compatible Evolution

Before Java 8, adding a new method to an interface broke all existing classes that implemented it. Default methods solve this — you can add new methods with a default implementation, and existing classes don't need to change. This is how Java's Collections API added stream() and forEach() to List without breaking millions of existing codebases.
Java
interface Vehicle {
    void start();    // all implementors must provide this

    // Default method — implementors get this for free, can override if needed
    default void stop() {
        System.out.println("Vehicle stopping — applying brakes");
    }

    default void fuelStatus() {
        System.out.println("Fuel level: checking...");
    }

    // Static method in interface — utility method, called on the interface itself
    static int maxSpeedLimit() {
        return 120;
    }
}

class Car implements Vehicle {
    public void start() {
        System.out.println("Car engine starting — vroom!");
    }
    // stop() and fuelStatus() inherited with default implementations

    @Override
    public void stop() {
        System.out.println("Car stopping — applying ABS brakes");
    }
}

Car car = new Car();
car.start();     // Car engine starting — vroom!
car.stop();      // Car stopping — applying ABS brakes (overridden)
car.fuelStatus(); // Fuel level: checking... (default)
System.out.println(Vehicle.maxSpeedLimit()); // 120 (static)