Java Interfaces
Complete guide to Java interfaces with examples. Learn interface declaration, implementation, multiple inheritance, default methods, and interface vs abstract class.
An interface in Java is a reference type that defines a contract of methods that a class must implement. Interfaces are used to achieve abstraction and multiple inheritance in Java, providing a way to specify what a class must do without defining how it should do it.
What is an Interface?
An interface is a collection of abstract methods (methods without implementation) and constants. It defines a contract that implementing classes must follow. Think of an interface as a blueprint that specifies what methods a class should have.
Tip 💡: An Interface is a Contract. If you sign it (implement it), you MUST do the work (implement methods). No excuses!
Basic Interface Syntax
interface InterfaceName {
// Constant declarations (public, static, final by default)
int CONSTANT_VALUE = 100;
// Abstract method declarations (public and abstract by default)
void method1();
int method2(String parameter);
}Creating and Implementing Interfaces
Example: Basic Interface
interface Animal {
// Constants (implicitly public, static, final)
String KINGDOM = "Animalia";
// Abstract methods (implicitly public and abstract)
void makeSound();
void move();
void eat();
}
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("Dog barks: Woof! Woof!");
}
@Override
public void move() {
System.out.println("Dog runs on four legs");
}
@Override
public void eat() {
System.out.println("Dog eats dog food");
}
}
class Bird implements Animal {
@Override
public void makeSound() {
System.out.println("Bird chirps: Tweet! Tweet!");
}
@Override
public void move() {
System.out.println("Bird flies in the sky");
}
@Override
public void eat() {
System.out.println("Bird eats seeds and insects");
}
}
class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal bird = new Bird();
System.out.println("Kingdom: " + Animal.KINGDOM);
System.out.println("\nDog behaviors:");
dog.makeSound();
dog.move();
dog.eat();
System.out.println("\nBird behaviors:");
bird.makeSound();
bird.move();
bird.eat();
}
}Multiple Inheritance with Interfaces
Java doesn't support multiple inheritance of classes, but it supports multiple inheritance through interfaces. A class can implement multiple interfaces.
Example: Multiple Interface Implementation
interface Flyable {
void fly();
int getMaxAltitude();
}
interface Swimmable {
void swim();
int getMaxDepth();
}
interface Walkable {
void walk();
int getMaxSpeed();
}
class Duck implements Flyable, Swimmable, Walkable {
@Override
public void fly() {
System.out.println("Duck flies at moderate altitude");
}
@Override
public int getMaxAltitude() {
return 1000; // meters
}
@Override
public void swim() {
System.out.println("Duck swims on water surface");
}
@Override
public int getMaxDepth() {
return 2; // meters
}
@Override
public void walk() {
System.out.println("Duck waddles on land");
}
@Override
public int getMaxSpeed() {
return 8; // km/h
}
}
class Penguin implements Swimmable, Walkable {
@Override
public void swim() {
System.out.println("Penguin swims underwater");
}
@Override
public int getMaxDepth() {
return 500; // meters
}
@Override
public void walk() {
System.out.println("Penguin walks on ice");
}
@Override
public int getMaxSpeed() {
return 5; // km/h
}
}
```java
class AnimalShowcase {
public static void main(String[] args) {
Duck duck = new Duck();
Penguin penguin = new Penguin();
System.out.println("=== Duck Abilities ===");
duck.fly();
duck.swim();
duck.walk();
System.out.println("Max altitude: " + duck.getMaxAltitude() + "m");
System.out.println("\n=== Penguin Abilities ===");
penguin.swim();
penguin.walk();
System.out.println("Max depth: " + penguin.getMaxDepth() + "m");
}
}classDiagram
class Flyable {
<<interface>>
+fly()
}
class Swimmable {
<<interface>>
+swim()
}
class Walkable {
<<interface>>
+walk()
}
class Duck {
+fly()
+swim()
+walk()
}
class Penguin {
+swim()
+walk()
}
Flyable <|.. Duck
Swimmable <|.. Duck
Walkable <|.. Duck
Swimmable <|.. Penguin
Walkable <|.. PenguinClass Diagram: Multiple Interface Implementation
Can a class implement multiple interfaces?
Interface Inheritance
Interfaces can extend other interfaces using the extends keyword.
interface Vehicle {
void start();
void stop();
}
interface LandVehicle extends Vehicle {
void accelerate();
void brake();
}
interface WaterVehicle extends Vehicle {
void sail();
void anchor();
}
interface AmphibiousVehicle extends LandVehicle, WaterVehicle {
void switchToLandMode();
void switchToWaterMode();
}
class AmphibiousCar implements AmphibiousVehicle {
private String mode = "land";
@Override
public void start() {
System.out.println("Amphibious car engine started");
}
@Override
public void stop() {
System.out.println("Amphibious car engine stopped");
}
@Override
public void accelerate() {
System.out.println("Accelerating on land");
}
@Override
public void brake() {
System.out.println("Braking on land");
}
@Override
public void sail() {
System.out.println("Sailing on water");
}
@Override
public void anchor() {
System.out.println("Anchoring in water");
}
@Override
public void switchToLandMode() {
mode = "land";
System.out.println("Switched to land mode");
}
@Override
public void switchToWaterMode() {
mode = "water";
System.out.println("Switched to water mode");
}
}Default Methods (Java 8+)
Since Java 8, interfaces can have default methods with implementation. This allows adding new methods to interfaces without breaking existing implementations.
interface Drawable {
// Abstract method
void draw();
// Default method
default void print() {
System.out.println("Printing: " + this.getClass().getSimpleName());
}
// Default method with logic
default void displayInfo() {
System.out.println("This is a drawable object");
draw(); // Calling abstract method
}
}
interface Colorable {
String getColor();
default void paintWithColor(String color) {
System.out.println("Painting with " + color + " color");
}
}
class Circle implements Drawable, Colorable {
private String color;
public Circle(String color) {
this.color = color;
}
@Override
public void draw() {
System.out.println("Drawing a circle");
}
@Override
public String getColor() {
return color;
}
}
class Rectangle implements Drawable, Colorable {
private String color;
public Rectangle(String color) {
this.color = color;
}
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
@Override
public String getColor() {
return color;
}
// Overriding default method
@Override
public void print() {
System.out.println("Custom printing for rectangle");
}
}
class DefaultMethodExample {
public static void main(String[] args) {
Circle circle = new Circle("Red");
Rectangle rectangle = new Rectangle("Blue");
System.out.println("=== Circle ===");
circle.draw();
circle.print(); // Using default method
circle.displayInfo(); // Using default method
System.out.println("Color: " + circle.getColor());
System.out.println("\n=== Rectangle ===");
rectangle.draw();
rectangle.print(); // Using overridden method
rectangle.paintWithColor("Green"); // Using default method from Colorable
}
}Marker Interfaces
A Marker Interface is an interface that has no methods or constants. It is used to "mark" or "tag" a class so that the JVM or a framework can treat it specially.
Examples:
Serializable: Marks a class as serializable.Cloneable: Marks a class as cloneable.Remote: Marks a class as a remote object.
interface SafeToDelete {
// No methods - just a marker
}
class TempFile implements SafeToDelete {
// implementation
}
class FileCleaner {
void clean(Object obj) {
if (obj instanceof SafeToDelete) {
System.out.println("Deleting file...");
}
}
}Static Methods in Interfaces (Java 8+)
Interfaces can also have static methods that belong to the interface itself.
interface MathUtils {
// Abstract method
double calculate();
// Static method
static double add(double a, double b) {
return a + b;
}
static double multiply(double a, double b) {
return a * b;
}
static void printWelcome() {
System.out.println("Welcome to MathUtils!");
}
}
class Calculator implements MathUtils {
private double result;
public Calculator(double initialValue) {
this.result = initialValue;
}
@Override
public double calculate() {
return result;
}
public void add(double value) {
result = MathUtils.add(result, value); // Using static method
}
public void multiply(double value) {
result = MathUtils.multiply(result, value); // Using static method
}
}
class StaticMethodExample {
public static void main(String[] args) {
MathUtils.printWelcome(); // Calling static method directly
Calculator calc = new Calculator(10);
calc.add(5);
calc.multiply(2);
System.out.println("Result: " + calc.calculate());
// Using static methods directly
double sum = MathUtils.add(10, 20);
double product = MathUtils.multiply(5, 6);
System.out.println("Sum: " + sum + ", Product: " + product);
}
}Real-World Example: Payment System
interface PaymentProcessor {
// Constants
double MAX_TRANSACTION_AMOUNT = 10000.0;
String CURRENCY = "USD";
// Abstract methods
boolean processPayment(double amount);
String getPaymentMethod();
double getTransactionFee(double amount);
// Default method
default boolean isValidAmount(double amount) {
return amount > 0 && amount <= MAX_TRANSACTION_AMOUNT;
}
default void logTransaction(double amount) {
System.out.println("Transaction logged: " + amount + " " + CURRENCY);
}
// Static method
static String formatCurrency(double amount) {
return String.format("%.2f %s", amount, CURRENCY);
}
}
interface SecurePayment {
boolean authenticate(String credentials);
void encrypt();
void decrypt();
default boolean isSecure() {
return true;
}
}
class CreditCardProcessor implements PaymentProcessor, SecurePayment {
private String cardNumber;
public CreditCardProcessor(String cardNumber) {
this.cardNumber = cardNumber;
}
@Override
public boolean processPayment(double amount) {
if (!isValidAmount(amount)) {
System.out.println("Invalid amount: " + amount);
return false;
}
encrypt();
System.out.println("Processing credit card payment of " +
PaymentProcessor.formatCurrency(amount));
decrypt();
logTransaction(amount);
return true;
}
@Override
public String getPaymentMethod() {
return "Credit Card";
}
@Override
public double getTransactionFee(double amount) {
return amount * 0.03; // 3% fee
}
@Override
public boolean authenticate(String credentials) {
System.out.println("Authenticating credit card...");
return credentials.equals("valid_pin");
}
@Override
public void encrypt() {
System.out.println("Encrypting credit card data");
}
@Override
public void decrypt() {
System.out.println("Decrypting credit card data");
}
}
class PayPalProcessor implements PaymentProcessor, SecurePayment {
private String email;
public PayPalProcessor(String email) {
this.email = email;
}
@Override
public boolean processPayment(double amount) {
if (!isValidAmount(amount)) {
System.out.println("Invalid amount: " + amount);
return false;
}
System.out.println("Processing PayPal payment of " +
PaymentProcessor.formatCurrency(amount));
logTransaction(amount);
return true;
}
@Override
public String getPaymentMethod() {
return "PayPal";
}
@Override
public double getTransactionFee(double amount) {
return amount * 0.025; // 2.5% fee
}
@Override
public boolean authenticate(String credentials) {
System.out.println("Authenticating PayPal account...");
return credentials.equals("valid_password");
}
@Override
public void encrypt() {
System.out.println("Encrypting PayPal data");
}
@Override
public void decrypt() {
System.out.println("Decrypting PayPal data");
}
}
class PaymentSystem {
public static void processPayments(PaymentProcessor[] processors, double amount) {
System.out.println("=== Payment Processing System ===\n");
for (PaymentProcessor processor : processors) {
System.out.println("Payment Method: " + processor.getPaymentMethod());
System.out.println("Transaction Fee: " +
PaymentProcessor.formatCurrency(processor.getTransactionFee(amount)));
boolean success = processor.processPayment(amount);
System.out.println("Payment Status: " + (success ? "SUCCESS" : "FAILED"));
System.out.println("---");
}
}
public static void main(String[] args) {
PaymentProcessor[] processors = {
new CreditCardProcessor("1234-5678-9012-3456"),
new PayPalProcessor("user@example.com")
};
processPayments(processors, 250.0);
}
}Interface vs Abstract Class
| Feature | Interface | Abstract Class |
|---|---|---|
| Methods | Abstract by default (can have default/static) | Can have both abstract and concrete methods |
| Variables | Only constants (public, static, final) | Can have instance variables |
| Inheritance | Multiple inheritance supported | Single inheritance only |
| Constructor | Cannot have constructors | Can have constructors |
| Access Modifiers | Methods are public by default | Can have any access modifier |
| When to Use | Define contracts, achieve multiple inheritance | Share code among related classes |
Example: When to Use Interface vs Abstract Class
// Use Interface: Define contract for unrelated classes
// interface
interface Polygon {
void getArea(int length, int breadth);
}
// implement the interface
class Rectangle implements Polygon {
public void getArea(int length, int breadth) {
System.out.println("The area of the rectangle is " + (length * breadth));
}
}Which keyword is used to implement an interface?
Here, Polygon is an interface. The Rectangle class implements the Polygon interface.
// Use Abstract Class: Share common code among related classes
abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// Concrete method
public void setColor(String color) {
this.color = color;
}
// Abstract method
public abstract double getArea();
}
class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}Best Practices for Interfaces
1. Keep Interfaces Focused
// Good: Single responsibility
interface FileReader {
String readFile(String path);
}
interface FileWriter {
void writeFile(String path, String content);
}
// Avoid: Too many responsibilities
interface FileHandler {
String readFile(String path);
void writeFile(String path, String content);
void deleteFile(String path);
void copyFile(String source, String dest);
// ... many more methods
}2. Use Default Methods Carefully
interface Sortable {
void sort();
// Good: Providing useful default behavior
default void sortDescending() {
sort();
reverse();
}
private void reverse() {
// Helper method implementation
}
}3. Design for Extension
interface EventHandler<T> {
void handle(T event);
// Allows for future extension without breaking existing code
default boolean canHandle(T event) {
return true;
}
}Key Points to Remember
- Interfaces define contracts that classes must implement
- All methods in interfaces are public and abstract by default (before Java 8)
- Interface variables are public, static, and final by default
- Classes can implement multiple interfaces (multiple inheritance)
- Interfaces can extend other interfaces
- Default methods (Java 8+) provide implementations in interfaces
- Static methods in interfaces belong to the interface itself
- Use interfaces for contracts and abstract classes for shared implementation
- Interfaces promote loose coupling and high cohesion
- Polymorphism works seamlessly with interfaces
Best Practice: Program to interfaces, not implementations. This makes your code more flexible, testable, and maintainable.
Challenge
Complete this chapter to unlock the next one.
Challenge
Task:
Create an interface 'Playable' with method 'play()'. Implement it in 'Guitar' to print 'Strumming'. Call play().Key Takeaways
- Contract: Defines what a class must do, not how.
- Multiple Inheritance: A class can implement multiple interfaces (
implements A, B). - Default Methods: Since Java 8, interfaces can have methods with bodies (
default void ...).
Common Pitfalls
[!WARNING] Constants Only: All variables in an interface are implicitly
public static final. You can't have normal instance variables.Public Methods: All methods are implicitly
public. You can't make themprivateorprotected(except private helper methods in Java 9+).
What's Next?
We've seen static a few times. What does it actually mean?
Master Static Keyword →
