Skip to content
Java abstraction 6 min read

Interfaces

An interface in Java is a pure contract — it declares what a class can do without specifying how. Any class that signs the contract by implementing the interface agrees to provide all of the defined behaviors. Interfaces are one of Java’s most powerful tools for writing flexible, loosely-coupled code.

What Is an Interface?

An interface looks like a class but starts with the interface keyword. Traditionally, all methods inside were implicitly public and abstract — no body, just a signature. A class “signs” the contract using the implements keyword.

interface Drawable {
    void draw();       // implicitly public abstract
    void resize(int factor);
}

class Circle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }

    @Override
    public void resize(int factor) {
        System.out.println("Resizing circle by factor " + factor);
    }
}
Drawing a circle
Resizing circle by factor 3

Note: A class that implements an interface must provide a body for every abstract method — otherwise it must be declared abstract itself.

Interface vs Abstract Class at a Glance

Both tools support abstraction, but they serve different purposes. See Abstract Class vs Interface for a deep-dive comparison.

FeatureInterfaceAbstract Class
Multiple “inheritance”A class can implement manyA class can extend only one
FieldsOnly public static final constantsAny field type
ConstructorNot allowedAllowed
Default implementationsYes (Java 8+, default methods)Yes (regular methods)
Best forDefining a role or capabilitySharing common state and behavior

A rough rule of thumb: use an interface when you want to say “this object can do X” (e.g., Serializable, Runnable, Comparable), and an abstract class when you want to say “this object IS a kind of X” with shared state.

Interface Variables (Constants)

Every field you declare inside an interface is automatically public static final. You cannot create instance variables.

interface MathConstants {
    double PI = 3.14159265358979;   // implicitly public static final
    int MAX_ITERATIONS = 1000;
}

class Calculator implements MathConstants {
    double circleArea(double r) {
        return PI * r * r;   // PI is inherited from the interface
    }
}

Tip: Prefer class constants or enum over interface constants for large projects — the “constant interface” pattern is considered an anti-pattern because it pollutes the implementing class’s namespace.

Implementing Multiple Interfaces

One of the biggest advantages over abstract classes is that a single class can implement any number of interfaces, giving Java its answer to multiple inheritance.

interface Flyable {
    void fly();
}

interface Swimmable {
    void swim();
}

class Duck implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("Duck is flying");
    }

    @Override
    public void swim() {
        System.out.println("Duck is swimming");
    }
}

This is how Java achieves safe multiple inheritance of behavior without the “Diamond Problem” that plagued C++. See Types of Inheritance for more detail.

Default Methods (Java 8+)

Before Java 8, adding a new method to an interface broke every class that implemented it. Java 8 introduced default methods — method bodies inside interfaces that serve as a fallback implementation.

interface Greeter {
    void greet(String name);

    // Default method — implementors can override or accept this
    default void greetAll(String[] names) {
        for (String name : names) {
            greet(name);
        }
    }
}

class FormalGreeter implements Greeter {
    @Override
    public void greet(String name) {
        System.out.println("Good day, " + name + ".");
    }
    // greetAll() is inherited for free
}
Good day, Alice.
Good day, Bob.

Note: If two interfaces provide a default method with the same signature and a class implements both, the compiler forces you to override it and resolve the ambiguity explicitly.

Static Methods in Interfaces (Java 8+)

Interfaces can also hold static utility methods. They belong to the interface itself and cannot be overridden.

interface StringUtils {
    static boolean isNullOrEmpty(String s) {
        return s == null || s.isEmpty();
    }
}

// Call it like StringUtils.isNullOrEmpty("hello")

Private Methods in Interfaces (Java 9+)

Java 9 added private (and private static) methods inside interfaces, letting you refactor shared logic between default methods without exposing it to implementors.

interface Logger {
    default void logInfo(String msg)  { log("INFO",  msg); }
    default void logError(String msg) { log("ERROR", msg); }

    private void log(String level, String msg) {
        System.out.println("[" + level + "] " + msg);
    }
}

Functional Interfaces and Lambdas (Java 8+)

An interface with exactly one abstract method is called a functional interface. You can implement it with a concise lambda expression instead of a full anonymous class.

@FunctionalInterface
interface Transformer {
    String transform(String input);
}

public class Main {
    public static void main(String[] args) {
        Transformer toUpper = s -> s.toUpperCase();
        Transformer shout  = s -> s.toUpperCase() + "!";

        System.out.println(toUpper.transform("hello"));
        System.out.println(shout.transform("hello"));
    }
}
HELLO
HELLO!

The @FunctionalInterface annotation is optional but recommended — the compiler will error if you accidentally add a second abstract method. Java’s standard library is full of functional interfaces: Runnable, Callable, Comparator, Predicate, Function, and more. See Functional Interfaces for the full picture.

Extending Interfaces

An interface can extend one or more other interfaces using extends, building a richer contract.

interface Animal {
    void breathe();
}

interface Pet extends Animal {
    void play();
}

class Dog implements Pet {
    @Override public void breathe() { System.out.println("Breathing..."); }
    @Override public void play()    { System.out.println("Fetching ball!"); }
}

Marker Interfaces

A marker interface has no methods at all — it just “tags” a class with a capability that the JVM or frameworks check at runtime.

// java.io.Serializable is the most famous example
public interface Serializable { }

// Your own marker
interface Auditable { }

class Order implements Auditable {
    // JPA or a framework can check: if (obj instanceof Auditable) { ... }
}

Common JDK marker interfaces: Serializable, Cloneable, RandomAccess. See Serialization and Object Cloning for real-world usage.

Under the Hood

When the JVM loads an interface, it stores metadata about all abstract method signatures in the constant pool of the .class file. There is no instantiation — no constructor bytecode is ever generated.

How method dispatch works: When a variable declared as an interface type calls a method, the JVM uses invokevirtual (for default methods) or invokeinterface bytecode instruction. invokeinterface is slightly more expensive than invokevirtual because the JVM must search the implementing class’s itable (interface method table) rather than the straightforward vtable used for class-based dispatch. Modern JIT compilers inline and de-virtualize frequent interface calls, so the overhead is usually negligible. See vtable & Dynamic Dispatch for the full picture.

Default methods and the diamond problem: The JVM’s resolution rules are: (1) the class’s own override wins, (2) the most specific interface wins, (3) ambiguity is a compile error that forces an explicit override. This is checked at compile time — not runtime — so you will never silently call the wrong default.

Memory: Interfaces themselves consume no heap — only their metadata in the metaspace. Each object that implements an interface carries an itable pointer (a slot in its class metadata) that maps interface method tokens to the concrete implementations.

Quick Reference: Interface Evolution by Java Version

Java VersionFeature Added
Java 1.0public abstract methods + public static final fields
Java 8default methods, static methods, lambda support
Java 9private and private static methods
Java 16+Interfaces can be sealed — restrict who can implement them

For sealed interfaces, see Sealed Classes.

Last updated June 13, 2026
Was this helpful?