Understanding Java Interfaces

Concept explanation of interfaces as contracts that classes implement

java (1.0+) 2025-11-03 interfaces oop polymorphism concepts

Description

Interfaces in Java define a contract that implementing classes must follow. They specify what methods a class must provide without dictating how they’re implemented. Interfaces enable polymorphism and help achieve loose coupling in design.

Key Concepts

What is an Interface?

  • A reference type that contains only constants, method signatures, default methods, static methods, and nested types
  • Cannot be instantiated directly
  • Defines a contract that implementing classes must fulfill
  • Supports multiple inheritance (a class can implement multiple interfaces)

Interface Evolution

  • Java 7 and earlier: Only abstract methods and constants
  • Java 8: Added default methods and static methods
  • Java 9: Added private methods
  • Java 16: Added sealed interfaces (preview)

Types of Methods

  • Abstract methods: Must be implemented by classes (implicitly public abstract)
  • Default methods: Provide default implementation (can be overridden)
  • Static methods: Called directly on interface (cannot be overridden)
  • Private methods: Helper methods (Java 9+)

Interface vs Abstract Class

  • Interfaces: Multiple inheritance, no instance variables, all methods public
  • Abstract classes: Single inheritance, can have instance variables, various access modifiers
  • Use interfaces for “can-do” relationships
  • Use abstract classes for “is-a” relationships with shared implementation

Functional Interfaces

  • Interface with exactly one abstract method
  • Can be implemented using lambda expressions
  • Examples: Runnable, Comparator, Function, Predicate
  • Marked with @FunctionalInterface annotation

Benefits

  • Polymorphism: Treat different implementations uniformly
  • Loose coupling: Depend on abstractions, not concrete classes
  • Multiple inheritance: Implement multiple interfaces
  • Contract enforcement: Guarantee certain methods exist
  • API design: Define clear boundaries between modules

Best Practices

  • Keep interfaces focused (Interface Segregation Principle)
  • Use descriptive names ending in -able or -er when appropriate
  • Prefer composition over inheritance
  • Use default methods for backward compatibility
  • Document interface contracts clearly

Common Patterns

  • Strategy pattern: Multiple implementations of an algorithm
  • Dependency injection: Program to interfaces
  • Adapter pattern: Implement interface to adapt incompatible classes
  • Marker interfaces: Empty interfaces for type identification

Code

RAW
// Basic interfaceinterface Drawable {    void draw(); // Implicitly public abstract        // Default method (Java 8+)    default void resize() {        System.out.println("Resizing...");    }        // Static method (Java 8+)    static void printInfo() {        System.out.println("This is a Drawable interface");    }}// Implementing interfaceclass Circle implements Drawable {    @Override    public void draw() {        System.out.println("Drawing a circle");    }}class Rectangle implements Drawable {    @Override    public void draw() {        System.out.println("Drawing a rectangle");    }        // Override default method (optional)    @Override    public void resize() {        System.out.println("Resizing rectangle specifically");    }}// Multiple interfacesinterface Flyable {    void fly();}interface Swimmable {    void swim();}class Duck implements Drawable, Flyable, Swimmable {    @Override    public void draw() {        System.out.println("Drawing a duck");    }        @Override    public void fly() {        System.out.println("Duck is flying");    }        @Override    public void swim() {        System.out.println("Duck is swimming");    }}// Functional interface@FunctionalInterfaceinterface Calculator {    int calculate(int a, int b);        // Can have default methods    default void print(int result) {        System.out.println("Result: " + result);    }}// UsageDrawable circle = new Circle();circle.draw();circle.resize(); // Uses default implementationDrawable.printInfo(); // Static method call// PolymorphismDrawable[] shapes = {new Circle(), new Rectangle()};for (Drawable shape : shapes) {    shape.draw();}// Functional interface with lambdaCalculator add = (a, b) -> a + b;Calculator multiply = (a, b) -> a * b;int sum = add.calculate(5, 3);int product = multiply.calculate(5, 3);

Comments

No comments yet. Be the first to comment!