Skip to content

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 implicitly public.
  • 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 against Vehicle works unchanged for Car, 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 of Car, Truck, etc., and a loop calling vehicle.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.