View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All

Interfaces in Java: Everything You Need to Know About Implementation, Types, and Best Practices

Updated on 29/04/20256,102 Views

Introduction

An interface in Java Programming is a blueprint of a class that contains abstract methods, default methods, static methods, and constant declarations. Interfaces are a core concept in Java programming that enables abstraction, multiple inheritance, and polymorphism. Unlike classes, interfaces cannot be instantiated directly; instead, they must be implemented by classes or extended by other interfaces. Understanding interfaces is crucial for creating flexible, maintainable, and scalable Java applications.

In this guide, we'll explore what interfaces are, how to implement them, the different types of interfaces in Java including functional and marker interfaces, and provide practical examples to solidify your understanding. We'll also compare interfaces with abstract classes to help you make informed design decisions in your Java projects.

Code like a pro as upGrad’s software engineering course helps you level up your Java skills with real-world projects and expert coaching.

What is an Interface in Java?

An interface in Java is essentially a contract that specifies what a class must do, without dictating how it should do it. It provides a way to achieve abstraction by separating what a class does from how it does it. This separation is fundamental to good object-oriented programming.

Characteristics of Interfaces

  1. Abstract Methods: By default, all methods declared in an interface are implicitly public and abstract (except default, static, and private methods introduced in Java 8 and 9).
  2. No Method Body: Traditional interface methods don't have implementation bodies; they only declare the method signature.
  3. Constants: All fields in an interface are implicitly public, static, and final.
  4. No Constructors: Interfaces cannot have constructors because they cannot be instantiated.
  5. Multiple Inheritance: A class can implement multiple interfaces, allowing Java to achieve a form of multiple inheritance without the complexities.

Take the next step in your tech journey with these top AI and data science courses:

Master’s in Data Science – LJMU

• M.Sc. in AI & Data Science – Jindal Global University

• PG Diploma in ML & AI – IIIT Bangalore

Basic Syntax of an Interface

public interface InterfaceName {
    // Constant declarations
    type CONSTANT_NAME = value;
    
    // Abstract method declarations
    returnType methodName(parameterList);
    
    // Default method (Java 8+)
    default returnType methodName(parameterList) {
        // Method body
    }
    
    // Static method (Java 8+)
    static returnType methodName(parameterList) {
        // Method body
    }
    
    // Private method (Java 9+)
    private returnType methodName(parameterList) {
        // Method body
    }
}

Check out: What Is Externalization In Java? Interface, Features & Example

Implementing Interfaces in Java

To use an interface, a class must implement it using the implements keyword and provide concrete implementations of all its abstract methods.

Java Interface Example

Let's start with a simple example of defining and implementing an interface:

// Define the interface
public interface Drawable {
    void draw(); // Abstract method
    
    // Default method (Java 8+)
    default void setColor(String color) {
        System.out.println("Setting color to: " + color);
    }
}

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

// Usage example
public class Main {
    public static void main(String[] args) {
        Drawable circle = new Circle();
        circle.draw(); // Output: Drawing a circle
        circle.setColor("Red"); // Output: Setting color to: Red
    }
}

In this example:

  • We define a Drawable interface with an abstract method draw() and a default method setColor().
  • The Circle class implements the Drawable interface and provides an implementation for the draw() method.
  • We can use the interface as a type for the object reference.

Implementing Multiple Interfaces

One powerful feature of interfaces is that a class can implement multiple interfaces:

// Another interface
public interface Resizable {
    void resize(double factor);
}

// Class implementing multiple interfaces
public class Rectangle implements Drawable, Resizable {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle with width: " + width + " and height: " + height);
    }
    
    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized. New dimensions - width: " + width + ", height: " + height);
    }
}

// Usage example
public class Main {
    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle(10, 20);
        rectangle.draw(); // Output: Drawing a rectangle with width: 10.0 and height: 20.0
        rectangle.resize(1.5); // Output: Rectangle resized. New dimensions - width: 15.0, height: 30.0
        rectangle.draw(); // Output: Drawing a rectangle with width: 15.0 and height: 30.0
    }
}

This example demonstrates how a single class can implement multiple interfaces, allowing for a flexible and modular design.

Types of Interfaces in Java

Java supports several types of interfaces, each with specific purposes and characteristics.

Functional Interface in Java

A functional interface is an interface that contains exactly one abstract method. Functional interfaces are the foundation of lambda expressions in Java 8 and later versions. These interfaces can have any number of default, static, or private methods, but must have only one abstract method.

// A functional interface example
@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
    
    // Multiple default methods are allowed
    default void printInfo() {
        System.out.println("This is a calculator interface");
    }
}

// Implementation using a class
public class Addition implements Calculator {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
}

// Usage with lambda expressions
public class Main {
    public static void main(String[] args) {
        // Traditional way
        Calculator addition = new Addition();
        System.out.println("10 + 5 = " + addition.calculate(10, 5)); // Output: 10 + 5 = 15
        
        // Using lambda expression
        Calculator subtraction = (a, b) -> a - b;
        System.out.println("10 - 5 = " + subtraction.calculate(10, 5)); // Output: 10 - 5 = 5
        
        // Using lambda with method reference
        Calculator multiplication = (a, b) -> a * b;
        System.out.println("10 * 5 = " + multiplication.calculate(10, 5)); // Output: 10 * 5 = 50
    }
}

The @FunctionalInterface annotation is not mandatory but it's a good practice to use it as it helps the compiler verify that the interface indeed has only one abstract method.

Some commonly used functional interfaces in Java include:

  • Runnable: Contains the run() method
  • Callable: Contains the call() method
  • Comparator: Contains the compare() method
  • Consumer: Contains the accept() method
  • Supplier: Contains the get() method
  • Function: Contains the apply() method
  • Predicate: Contains the test() method

Marker Interface in Java

A marker interface is an interface that has no methods or constants. It serves as a tag to inform the compiler about special handling needed for the implementing class. The marker interface simply "marks" a class as having a certain property.

// Example of a marker interface
public interface Serializable {
    // No methods or constants
}

// Another example of a marker interface
public interface Cloneable {
    // No methods or constants
}

// Class implementing a marker interface
public class Student implements Serializable {
    private String name;
    private int id;
    
    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }
    
    // Getters and setters
}

Some well-known marker interfaces in Java are:

  • java.io.Serializable: Marks a class as serializable, allowing its objects to be converted to byte streams
  • java.lang.Cloneable: Indicates that a class can be cloned using the Object.clone() method
  • java.util.RandomAccess: Indicates that a List implementation supports fast random access

Also read: Serializable Interface in Java

Normal Interface

A normal interface is one that has one or more abstract methods. This is the traditional form of interface in Java.

// Example of a normal interface
public interface Shape {
    double calculateArea();
    double calculatePerimeter();
    void display();
}

// Implementing a normal interface
public class Square implements Shape {
    private double side;
    
    public Square(double side) {
        this.side = side;
    }
    
    @Override
    public double calculateArea() {
        return side * side;
    }
    
    @Override
    public double calculatePerimeter() {
        return 4 * side;
    }
    
    @Override
    public void display() {
        System.out.println("Square with side: " + side);
        System.out.println("Area: " + calculateArea());
        System.out.println("Perimeter: " + calculatePerimeter());
    }
}

// Usage example
public class Main {
    public static void main(String[] args) {
        Shape square = new Square(5);
        square.display();
        // Output:
        // Square with side: 5.0
        // Area: 25.0
        // Perimeter: 20.0
    }
}

Interface Evolution in Java

The concept of interfaces in Java has evolved significantly over different Java versions.

Java 8 Interface Features

Java 8 introduced two major additions to interfaces:

  1. Default Methods: Methods with implementation that are provided in the interface itself.
  2. Static Methods: Methods that belong to the interface rather than to implementing classes.
public interface Vehicle {
    // Abstract method
    void accelerate();
    
    // Default method
    default void brake() {
        System.out.println("Vehicle is braking");
    }
    
    // Static method
    static void info() {
        System.out.println("Vehicles are used for transportation");
    }
}

public class Car implements Vehicle {
    @Override
    public void accelerate() {
        System.out.println("Car is accelerating");
    }
    
    // No need to implement brake() as it has a default implementation
}

public class Main {
    public static void main(String[] args) {
        Vehicle car = new Car();
        car.accelerate(); // Output: Car is accelerating
        car.brake(); // Output: Vehicle is braking
        
        // Calling static method from interface
        Vehicle.info(); // Output: Vehicles are used for transportation
    }
}

Java 9 Interface Features

Java 9 introduced private methods in interfaces, both static and non-static. These help in better code organization and reuse within the interface itself.

public interface Logger {
    default void logInfo(String message) {
        log(message, "INFO");
    }
    
    default void logWarning(String message) {
        log(message, "WARNING");
    }
    
    default void logError(String message) {
        log(message, "ERROR");
    }
    
    // Private method for code reuse within the interface
    private void log(String message, String level) {
        System.out.println("[" + level + "] " + message);
    }
    
    // Private static method
    private static String formatTime() {
        return java.time.LocalTime.now().toString();
    }
}

public class FileLogger implements Logger {
    // No need to implement any method as all methods in the interface have implementations
}

public class Main {
    public static void main(String[] args) {
        Logger logger = new FileLogger();
        logger.logInfo("Application started"); // Output: [INFO] Application started
        logger.logWarning("Low memory"); // Output: [WARNING] Low memory
        logger.logError("Connection failed"); // Output: [ERROR] Connection failed
    }
}

The Runnable Interface in Java

The Runnable interface is one of the most commonly used functional interfaces in Java. It's primarily used for executing code in a separate thread.

// Example of Runnable interface usage
public class TaskRunner implements Runnable {
    private String taskName;
    
    public TaskRunner(String taskName) {
        this.taskName = taskName;
    }
    
    @Override
    public void run() {
        System.out.println("Executing task: " + taskName);
        try {
            // Simulate work
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Task completed: " + taskName);
    }
}

public class Main {
    public static void main(String[] args) {
        // Create and start threads using Runnable
        Thread thread1 = new Thread(new TaskRunner("Data processing"));
        Thread thread2 = new Thread(new TaskRunner("File backup"));
        
        thread1.start();
        thread2.start();
        
        // Using lambda expression with Runnable
        Thread thread3 = new Thread(() -> {
            System.out.println("Executing task: Email notification");
            System.out.println("Task completed: Email notification");
        });
        
        thread3.start();
    }
}

The output might look like:

Executing task: Data processing

Executing task: File backup

Executing task: Email notification

Task completed: Email notification

Task completed: Data processing

Task completed: File backup

Note that the exact order of output might vary due to thread scheduling.

Interface vs Abstract Class in Java

Understanding when to use an interface versus an abstract class is crucial for good Java design. Here's a comparison of both:

Feature

Interface

Abstract Class

Multiple Inheritance

A class can implement multiple interfaces

A class can extend only one abstract class

State

Cannot have instance variables (except constants)

Can have instance variables to hold state

Constructors

Cannot have constructors

Can have constructors

Method Implementation

Prior to Java 8, could not have method implementations

Can have method implementations

Access Modifiers

All methods are implicitly public

Can have methods with different access modifiers

Fields

All fields are implicitly public, static, and final

Can have fields with different access modifiers

Purpose

To define a contract of what a class can do

To provide a common base implementation for subclasses

When to Use Abstract Class and Interface in Java

Use an abstract class when:

  • You want to share code among closely related classes
  • You expect classes that extend your abstract class to have many common methods or fields
  • You want to declare non-static or non-final fields
  • You need to provide a partial implementation of a complex feature

Use an interface when:

  • You expect unrelated classes to implement your interface
  • You want to specify the behavior of a particular data type but not concerned about who implements it
  • You want to take advantage of multiple inheritance
  • You want to separate the definition of a method from its implementation

Example Comparing Interface and Abstract Class

// Abstract class
public abstract class Animal {
    // State
    protected String name;
    
    // Constructor
    public Animal(String name) {
        this.name = name;
    }
    
    // Concrete method
    public void breathe() {
        System.out.println(name + " is breathing");
    }
    
    // Abstract method
    public abstract void makeSound();
}

// Interface
public interface Pet {
    void play();
    
    default void groom() {
        System.out.println("Pet is being groomed");
    }
}

// Class extending abstract class
public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    
    @Override
    public void makeSound() {
        System.out.println(name + " barks");
    }
}

// Class implementing interface
public class Cat implements Pet {
    private String name;
    
    public Cat(String name) {
        this.name = name;
    }
    
    @Override
    public void play() {
        System.out.println(name + " is playing with a yarn ball");
    }
}

// Class extending abstract class and implementing interface
public class Puppy extends Animal implements Pet {
    public Puppy(String name) {
        super(name);
    }
    
    @Override
    public void makeSound() {
        System.out.println(name + " whines");
    }
    
    @Override
    public void play() {
        System.out.println(name + " is playing fetch");
    }
}

// Usage example
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        dog.breathe(); // Output: Buddy is breathing
        dog.makeSound(); // Output: Buddy barks
        
        Cat cat = new Cat("Whiskers");
        cat.play(); // Output: Whiskers is playing with a yarn ball
        cat.groom(); // Output: Pet is being groomed
        
        Puppy puppy = new Puppy("Max");
        puppy.breathe(); // Output: Max is breathing
        puppy.makeSound(); // Output: Max whines
        puppy.play(); // Output: Max is playing fetch
        puppy.groom(); // Output: Pet is being groomed
    }
}

Java.util Package Interfaces

The java.util package contains many important interfaces. Here are some commonly used interfaces from this package:

  1. Collection: The root interface in the collection hierarchy.
  2. List: An ordered collection that allows duplicate elements.
  3. Set: A collection that does not allow duplicate elements.
  4. Map: Maps keys to values, without duplicate keys.
  5. Iterator: Used to iterate through collection elements.
  6. Comparator: Used for custom sorting of objects.
  7. Deque: A linear collection that supports element insertion and removal at both ends.

Let's see an example using some of these interfaces:

import java.util.*;

public class JavaUtilInterfacesExample {
    public static void main(String[] args) {
        // List interface example
        List<String> namesList = new ArrayList<>();
        namesList.add("Alice");
        namesList.add("Bob");
        namesList.add("Charlie");
        
        System.out.println("List elements: " + namesList);
        
        // Set interface example
        Set<Integer> numbersSet = new HashSet<>();
        numbersSet.add(10);
        numbersSet.add(20);
        numbersSet.add(10); // Duplicate - will not be added
        
        System.out.println("Set elements: " + numbersSet);
        
        // Map interface example
        Map<String, Integer> ageMap = new HashMap<>();
        ageMap.put("Alice", 25);
        ageMap.put("Bob", 30);
        ageMap.put("Charlie", 35);
        
        System.out.println("Map entries:");
        for (Map.Entry<String, Integer> entry : ageMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        
        // Comparator interface example
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 25));
        people.add(new Person("Bob", 30));
        people.add(new Person("Charlie", 20));
        
        // Sort by age using Comparator
        Collections.sort(people, new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p1.getAge() - p2.getAge();
            }
        });
        
        System.out.println("\nPeople sorted by age:");
        for (Person person : people) {
            System.out.println(person.getName() + ": " + person.getAge());
        }
        
        // Same sort using lambda expression
        Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));
        
        System.out.println("\nPeople sorted by name:");
        for (Person person : people) {
            System.out.println(person.getName() + ": " + person.getAge());
        }
    }
}

class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
}

Output:

List elements: [Alice, Bob, Charlie]

Set elements: [20, 10]

Map entries:

Bob: 30

Alice: 25

Charlie: 35

People sorted by age:

Charlie: 20

Alice: 25

Bob: 30

People sorted by name:

Alice: 25

Bob: 30

Charlie: 20

Conclusion

Interfaces in Java are vital for building flexible, modular, and maintainable applications. They enable abstraction, polymorphism, and a form of multiple inheritance, supporting better design practices. Java interfaces have evolved from basic abstract methods to advanced features like functional interfaces and default methods to meet modern development needs.

Mastering when to use interfaces over abstract classes promotes clean architecture and adherence to principles like Interface Segregation. More than just syntax, interfaces act as powerful contracts that guide system design and improve code scalability.

Frequently Asked Questions (FAQs)

1. What is an interface in Java with example?

An interface in Java is a reference type that contains a collection of abstract methods and constants. It serves as a contract for classes that implement it. For example, a Printable interface might declare a print() method, and any class implementing this interface must provide an implementation for this method. This enables polymorphic behavior where different objects can respond to the same method call in different ways.

public interface Printable {
    void print();
}

class Document implements Printable {
    @Override
    public void print() {
        System.out.println("Printing document...");
    }
}

2. What is a functional interface in Java?

A functional interface in Java is an interface that contains exactly one abstract method. Functional interfaces are used as the basis for lambda expressions in Java 8 and above. The @FunctionalInterface annotation is used to ensure that the interface has only one abstract method. Examples include Runnable, Callable, and Comparator. Functional interfaces can have any number of default, static, or private methods as long as there is only one abstract method.

3. What is a marker interface in Java?

A marker interface in Java is an interface that doesn't declare any methods or constants. It serves as a "marker" that tells the JVM that the implementing class possesses a certain capability. Examples include Serializable, Cloneable, and RandomAccess. The JVM provides special treatment to classes implementing marker interfaces. For instance, only classes implementing Serializable can be serialized to a byte stream.

4. What is the difference between class and interface in Java?

The main differences between a class and interface in Java are:

  1. A class can have instance variables, while an interface can only have constants.
  2. A class can provide implementation for its methods, while traditional interfaces only declare methods.
  3. A class can be instantiated, while an interface cannot.
  4. A class can extend only one class, but can implement multiple interfaces.
  5. Methods in a class can have any access modifier, while interface methods are implicitly public.

5. When should I use an abstract class instead of an interface in Java?

Use an abstract class when:

  1. You want to share code among closely related classes.
  2. You need to have non-static or non-final fields.
  3. You want to provide a common base implementation for subclasses.
  4. You need to define protected or private methods.

Use an interface when:

  1. You want unrelated classes to implement a common behavior.
  2. You want to take advantage of multiple inheritance.
  3. You want to specify what a class can do without dictating how it should do it.
  4. You want to define a contract without any implementation details.

6. What is the Runnable interface in Java?

The Runnable interface is a functional interface in Java used primarily for defining tasks that can be executed by a separate thread. It contains a single method, run(), which doesn't accept any parameters or return any value. The Runnable interface is commonly used with the Thread class to create and execute tasks concurrently.

public class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println("Task is running in a thread");
    }
}

// Usage
Thread thread = new Thread(new MyTask());
thread.start();

7. Which of the following is an interface in Java.util package?

The Java.util package contains several interfaces including:

  • Collection
  • List
  • Set
  • Map
  • Iterator
  • Comparator
  • Deque
  • Queue
  • SortedSet
  • SortedMap

These interfaces form the foundation of the Java Collections Framework and provide standardized ways to manipulate groups of objects.

8. Can an interface extend another interface in Java?

Yes, an interface can extend one or more other interfaces using the extends keyword. When an interface extends another interface, it inherits all the abstract methods, default methods, and static methods from the parent interface. A class implementing the child interface must implement all abstract methods from both the child and parent interfaces.

public interface Vehicle {
    void move();
}

public interface FlyingVehicle extends Vehicle {
    void fly();
}

public class Airplane implements FlyingVehicle {
    @Override
    public void move() {
        System.out.println("Airplane is moving on the runway");
    }
    
    @Override
    public void fly() {
        System.out.println("Airplane is flying in the sky");
    }
}

9. Can an interface have a constructor?

No, an interface cannot have a constructor. Constructors are used to initialize the state of an object, but interfaces don't have state (except constants). Since interfaces cannot be instantiated, there is no need for a constructor. All methods in interfaces are abstract, static, default, or private, and fields are constants.

10. Can an interface have private methods?

Yes, since Java 9, interfaces can have private methods. These private methods can be either static or instance methods and are only accessible within the interface itself. They cannot be accessed by implementing classes. Private methods in interfaces are primarily used for code reuse within the interface, especially when default methods share common code.

public interface Logger {
    default void logInfo(String message) {
        log(message, "INFO");
    }
    
    default void logError(String message) {
        log(message, "ERROR");
    }
    
    // Private method for code reuse
    private void log(String message, String level) {
        System.out.println("[" + level + "] " + message);
    }
}

11. What happens if a class implements two interfaces with default methods having the same signature?

If a class implements two interfaces that contain default methods with the same signature, the Java compiler will report a conflict. To resolve this conflict, the implementing class must override the default method and provide its own implementation. The class can still access the default implementations from either interface using the InterfaceName.super.methodName() syntax.

public interface A {
    default void display() {
        System.out.println("Display from A");
    }
}

public interface B {
    default void display() {
        System.out.println("Display from B");
    }
}

public class C implements A, B {
    // Must override to resolve conflict
    @Override
    public void display() {
        // Can call either default implementation
        A.super.display();
        // or
        B.super.display();
        // or provide a completely new implementation
        System.out.println("Display from C");
    }
}
image

Take the Free Quiz on Java

Answer quick questions and assess your Java knowledge

right-top-arrow
image
Join 10M+ Learners & Transform Your Career
Learn on a personalised AI-powered platform that offers best-in-class content, live sessions & mentorship from leading industry experts.
advertise-arrow

Free Courses

Explore Our Free Software Tutorials

upGrad Learner Support

Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)

text

Indian Nationals

1800 210 2020

text

Foreign Nationals

+918068792934

Disclaimer

1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.

2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.