Codectionary / Developer documentation / Java

Interfaces

An interface defines a contract of methods that implementing classes must provide, without specifying how those methods work internally. Unlike a class, an interface cannot be instantiated directly - it only declares what a class can do, not how. A class uses the 'implements' keyword to fulfill an interface's contract, and a single class can implement multiple interfaces, which is Java's way of achieving a form of multiple inheritance.

Syntax

interface InterfaceName {\n  returnType methodName(parameters);\n}

Examples

Basic Interface

Defining a contract and implementing it in a class.

public interface Shape {
    double area();
    double perimeter();
}

public class Rectangle implements Shape {
    private double width, height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double area() {
        return width * height;
    }

    @Override
    public double perimeter() {
        return 2 * (width + height);
    }
}

// Usage
Shape rect = new Rectangle(5, 3);
System.out.println(rect.area());  // 15.0

Implementing Multiple Interfaces

A class can implement more than one interface, gaining the contract of each.

interface Swimmer {
    void swim();
}

interface Runner {
    void run();
}

public class Triathlete implements Swimmer, Runner {
    @Override
    public void swim() {
        System.out.println("Swimming");
    }

    @Override
    public void run() {
        System.out.println("Running");
    }
}

Triathlete athlete = new Triathlete();
athlete.swim();
athlete.run();

Default and Static Methods

Since Java 8, interfaces can include default methods with a body, and static utility methods.

interface Vehicle {
    void drive();

    default void honk() {  // has a body, implementing classes can use it as-is
        System.out.println("Beep beep!");
    }

    static Vehicle createDefault() {  // static factory-like helper
        return () -> System.out.println("Driving a default vehicle");
    }
}

public class Car implements Vehicle {
    @Override
    public void drive() {
        System.out.println("Driving a car");
    }
}

Car car = new Car();
car.drive();
car.honk();  // uses the default implementation

Interface as a Type Reference

Using an interface as the declared type lets you write flexible code that works with any implementation.

interface PaymentMethod {
    void pay(double amount);
}

class CreditCard implements PaymentMethod {
    public void pay(double amount) {
        System.out.println("Paid $" + amount + " with credit card");
    }
}

class PayPal implements PaymentMethod {
    public void pay(double amount) {
        System.out.println("Paid $" + amount + " with PayPal");
    }
}

public class Checkout {
    public static void processPayment(PaymentMethod method, double amount) {
        method.pay(amount);  // works with ANY implementation
    }

    public static void main(String[] args) {
        processPayment(new CreditCard(), 50.0);
        processPayment(new PayPal(), 30.0);
    }
}

Best practices

  • Program to an interface rather than a concrete class (declare variables as 'Shape', not 'Rectangle') for more flexible, decoupled code
  • Use interfaces to define capabilities that unrelated classes might share, rather than forcing an inheritance hierarchy
  • Keep interfaces small and focused (Interface Segregation Principle) - many specific interfaces beat one large, do-everything interface
  • Use default methods sparingly, mainly for adding new functionality to an interface without breaking existing implementing classes

Runtime & versions

Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Java Language Specification

Specifications & further reading