Interfaces — cheat sheet
From: fundamentals/15-interfaces.md.
- What: a contract of method signatures with no bodies (
;instead) — the what, not the how.public interface Vehicle { double getMaxSpeed(); void start(); void stop(); }. All methods are implicitlypublic. - Implementing one:
class Car implements Vehicle { ... }, providing a real body for each interface method, each annotated@Override. - Why it matters — programming to an interface: a variable/parameter/collection can be typed as the interface (
Vehicle) rather than a concrete class (Car), so code written againstVehicleworks unchanged forCar,Truck, or any future class that implements it. This is the mechanism behind writing reusable code: depend on what something can do, not which concrete class does it. - Practical payoff: a
List<Vehicle>can hold a mix ofCar,Truck, etc., and a loop callingvehicle.start()works identically for all of them without knowing or caring which concrete type each element actually is. - Interview framing: this is the Java mechanism behind dependency injection working the way it does in Spring — a service can depend on an interface type, and Spring injects whichever concrete bean implements it, without the dependent class needing to know or change. Concrete worked example: 10-dependency-injection.md.
Advanced: what interfaces can hold (Java 8+)
From: fundamentals/16-interfaces-advanced.md. Historically interfaces held only abstract method signatures; Java 8 (alongside Streams) added:
- Constant variables — a value used everywhere/shared config; changing it changes behavior across every implementer without touching their code.
- Default methods — a method with a real body that implementers get for free, only overriding it where they need different behavior. Also used as a fallback when a specific implementation isn't provided.
- Static methods — utility methods that don't depend on instance state; an alternative to a separate utility class. (Can't be used for
public static void main.) - Private methods / private static methods — factor out logic shared between an interface's own default/static methods, same motivation as private helpers in a regular class.
Best practice is still to mostly keep interfaces to abstract methods — these extra features solve specific problems (shared config, safe defaults across many implementations), not a reason to move general logic into interfaces by default.