Java Interfaces - Functional, Marker and Nested Interfaces
1. What is an Interface?
An interface in Java is a reference type that defines a contract — a set of method signatures that any implementing class must fulfil. Think of it as an agreement: "Any class that says it implements this interface promises to provide these behaviours."
Key rules for interfaces (before Java 8):
-
All methods are implicitly
public abstract -
All fields are implicitly
public static final(constants) - Interfaces cannot be instantiated directly
- A class can implement multiple interfaces
- An interface can extend multiple interfaces
Java 8+ added
default and
static methods to interfaces.
Java 9+ added
private methods. The core contract
concept remains unchanged.
2. Defining and Implementing an Interface
Use the interface keyword to define
and implements to use it in a class.
The implementing class must provide a body for every abstract
method in the interface, or itself be declared
abstract.
// Define the interface
public interface Drawable {
// public abstract — implicit; no need to write them
void draw();
void resize(double factor);
// Default method (Java 8+) — optional to override
default void printInfo() {
System.out.println("This is a Drawable object.");
}
}
// Implement the interface in a class
public class Circle implements Drawable {
double radius;
String color;
public Circle(double radius, String color) {
this.radius = radius;
this.color = color;
}
@Override
public void draw() {
System.out.println("Drawing a " + color + " circle with radius " + radius);
}
@Override
public void resize(double factor) {
radius *= factor;
System.out.println("Circle resized. New radius: " + radius);
}
}
public class Square implements Drawable {
double side;
public Square(double side) {
this.side = side;
}
@Override
public void draw() {
System.out.println("Drawing a square with side " + side);
}
@Override
public void resize(double factor) {
side *= factor;
System.out.println("Square resized. New side: " + side);
}
@Override
public void printInfo() { // optionally override default method
System.out.println("Square: side = " + side);
}
}
public class Main {
public static void main(String[] args) {
Drawable c = new Circle(5.0, "red"); // interface reference
Drawable s = new Square(4.0);
c.draw(); // Drawing a red circle with radius 5.0
c.resize(2.0); // Circle resized. New radius: 10.0
c.printInfo(); // This is a Drawable object.
s.draw(); // Drawing a square with side 4.0
s.printInfo(); // Square: side = 4.0 (overridden)
}
}
Circle resized. New radius: 10.0
This is a Drawable object.
Drawing a square with side 4.0
Square: side = 4.0
3. Interface vs Abstract Class
| Feature | Interface | Abstract Class |
|---|---|---|
| Keyword |
interface /
implements
|
abstract class /
extends
|
| Instantiation | Cannot be instantiated | Cannot be instantiated |
| Constructors | No | Yes |
| Instance fields | No (only public static final) |
Yes (any access modifier) |
| Method types | abstract, default, static (Java 8+) | abstract + concrete |
| Multiple inheritance | A class can implement many interfaces | A class can extend only one |
| Access modifiers on methods | Always public (implicit) |
Any access modifier |
| Speed | Slightly slower (extra lookup) | Slightly faster |
| Best used when | Defining capabilities/contracts across unrelated classes | Sharing common code & state among related classes |
Rule of thumb: Prefer interfaces when you want
to define a capability (e.g.,
Comparable,
Serializable). Use abstract classes
when you want to share code and state among closely
related classes.
4. Multiple Interface Implementation
A Java class can implement multiple interfaces simultaneously, separated by commas. This is Java's approach to achieving multiple inheritance of type without the complexity of multiple class inheritance.
public interface Flyable {
void fly();
default String getMode() { return "flying"; }
}
public interface Swimmable {
void swim();
default String getMode() { return "swimming"; }
}
public interface Walkable {
void walk();
}
// Duck implements all three interfaces
public class Duck implements Flyable, Swimmable, Walkable {
private String name;
public Duck(String name) { this.name = name; }
@Override
public void fly() {
System.out.println(name + " is flying!");
}
@Override
public void swim() {
System.out.println(name + " is swimming!");
}
@Override
public void walk() {
System.out.println(name + " is walking!");
}
// MUST override getMode() — both Flyable and Swimmable define it
// (this resolves the diamond problem for default methods)
@Override
public String getMode() {
return Flyable.super.getMode() + " and " + Swimmable.super.getMode();
}
}
public class Main {
public static void main(String[] args) {
Duck duck = new Duck("Donald");
duck.fly();
duck.swim();
duck.walk();
System.out.println("Duck modes: " + duck.getMode());
// Polymorphic references
Flyable f = duck; f.fly();
Swimmable s = duck; s.swim();
}
}