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
implementsan interface must provide a body for every abstract method — otherwise it must be declaredabstractitself.
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.
| Feature | Interface | Abstract Class |
|---|---|---|
| Multiple “inheritance” | A class can implement many | A class can extend only one |
| Fields | Only public static final constants | Any field type |
| Constructor | Not allowed | Allowed |
| Default implementations | Yes (Java 8+, default methods) | Yes (regular methods) |
| Best for | Defining a role or capability | Sharing 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
classconstants orenumover 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
defaultmethod 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 Version | Feature Added |
|---|---|
| Java 1.0 | public abstract methods + public static final fields |
| Java 8 | default methods, static methods, lambda support |
| Java 9 | private and private static methods |
| Java 16+ | Interfaces can be sealed — restrict who can implement them |
For sealed interfaces, see Sealed Classes.
Related Topics
- Abstract Class — understand the sibling tool for sharing state alongside behavior
- Abstract Class vs Interface — side-by-side comparison to help you choose the right abstraction
- Functional Interfaces — how single-abstract-method interfaces power lambda expressions
- Lambda Expressions — write concise implementations of functional interfaces
- Polymorphism — how interfaces enable one variable to reference many types
- Default Methods — deeper coverage of interface default methods added in Java 8