Java Tutorial: Introduction to Java Interfaces

Java is a powerful and versatile programming language. It supports object-oriented programming through features like classes and interfaces. In this tutorial, you’ll learn Java interfaces, how to use them, and why they’re essential.

What Is a Java Interface?

A Java interface defines a contract. It specifies methods that a class must implement. Think of it as a blueprint. It tells the class what to do but not how to do it.

Interfaces do not contain method bodies. Instead, they list method signatures. This allows different classes to implement the same methods in other ways.

Here’s a simple example:

interface Animal {
    void makeSound();
}

The Animal interface defines one method: makeSound(). Any class that implements this interface must define that method.

Why Use Interfaces in Java?

Interfaces allow you to achieve abstraction. You can hide the implementation details and focus on what a class should do.

They also help with polymorphism. You can use interfaces to create flexible and reusable code. For example, if multiple classes implement the same interface, you can treat them similarly.

Here’s a benefit in action:

public class Dog implements Animal {
    public void makeSound() {
        System.out.println("Woof");
    }
}

public class Cat implements Animal {
    public void makeSound() {
        System.out.println("Meow");
    }
}

Now, you can write:

Animal myPet = new Dog();
myPet.makeSound();  // Output: Woof

Later, you can switch to:

myPet = new Cat();
myPet.makeSound();  // Output: Meow

Declaring an Interface in Java

To declare an interface, use the interface keyword:

public interface Vehicle {
    void start();
    void stop();
}

The Vehicle interface declares two methods. Any class that implements Vehicle both methods must provide concrete implementations.

Implementing an Interface

To use an interface, a class must implement it using the implements Keyword:

public class Car implements Vehicle {
    public void start() {
        System.out.println("Car starts");
    }

    public void stop() {
        System.out.println("Car stops");
    }
}

If the class does not implement all the interface methods, it must be declared abstract.

Interface vs Abstract Class

You might wonder: Why use an interface when abstract classes exist?

Here’s the difference:

  • A class can implement multiple interfaces.
  • A class can extend only one abstract class.
  • Interfaces cannot have constructors.
  • Interfaces define only method signatures (until Java 8 and later).

Use interfaces when you need to enforce behavior across unrelated classes. Use abstract classes when you have shared code or state that needs to be reused across multiple classes.

Java Interface and Multiple Inheritance

Java does not support multiple inheritance with classes. But it does with interfaces.

A class can implement multiple interfaces:

interface Camera {
    void takePhoto();
}

interface GPS {
    void navigate();
}

class Smartphone implements Camera, GPS {
    public void takePhoto() {
        System.out.println("Photo taken");
    }

    public void navigate() {
        System.out.println("Navigating to destination");
    }
}

Here, Smartphone inherits behavior from both Camera and GPS.

Default Methods in Interfaces (Java 8+)

Before Java 8, interfaces could only have abstract methods. Java 8 introduced default methods. These have a method body and provide default behavior.

Example:

interface Message {
    default void greet() {
        System.out.println("Hello");
    }

    void send();
}

Now, any class implementing Message gets a default greet() method.

class Email implements Message {
    public void send() {
        System.out.println("Sending Email");
    }
}

You can override the default method if needed.

Static Methods in Interfaces

Java 8 also introduced static methods in interfaces.

Example:

interface Calculator {
    static int add(int a, int b) {
        return a + b;
    }
}

To use this method, call it with the interface name:

int result = Calculator.add(3, 4);
System.out.println(result);  // Output: 7

Functional Interfaces and Lambda Expressions

functional interface is an interface with only one abstract method. These are used in lambda expressions.

Example of a Printer:

@FunctionalInterface
interface Printer {
    void print(String message);
}

You can use a lambda like this:

Printer p = msg -> System.out.println(msg);
p.print("Hello with Lambda");

Output

Hello with Lambda

Example of a Calculator:

@FunctionalInterface
public interface Calculator {
    int operation(int a, int b);
}

You can use a lambda like this:

public class FunctionalInterfaceExample {
    public static void main(String[] args) {
        Calculator add = (a, b) -> a + b;
        Calculator multiply = (a, b) -> a * b;

        System.out.println("Addition: " + add.operation(5, 3));
        System.out.println("Multiplication: " + multiply.operation(5, 3));
    }
}

Output

Addition: 8
Multiplication: 15

Java has built-in functional interfaces in the java.util.function package, like PredicateFunction, and Consumer.

Example using Predicate<T>

Predicate<T> is a functional interface that takes a single argument and returns a boolean.

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        Predicate<String> isNotEmpty = str -> str != null && !str.isEmpty();

        System.out.println(isNotEmpty.test("Hello")); // true
        System.out.println(isNotEmpty.test(""));      // false
        System.out.println(isNotEmpty.test(null));    // false
    }
}

Example using Function<T, R>

Function<T, R> takes one argument of type T and returns a result of type R.

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        Function<String, Integer> stringLength = str -> str.length();

        System.out.println(stringLength.apply("OpenAI"));   // 6
        System.out.println(stringLength.apply("ChatGPT"));  // 7
    }
}

Marker Interfaces

marker interface has no methods or fields. It marks a class with metadata.

Example:

interface Serializable {
}

Classes that implement Serializable can be serialized. The JVM uses this information at runtime.

Interface Inheritance

An interface can extend another interface. This allows you to build hierarchies.

interface Readable {
    void read();
}

interface Writable extends Readable {
    void write();
}

A class that implements Writable both read() and write().

Best Practices When Using Interfaces

  1. Use interfaces to define behavior, not state.
  2. Favor interfaces over abstract classes when possible.
  3. Use meaningful method names to describe the contract.
  4. Document the purpose of each interface.
  5. Avoid using interfaces for constants; instead, use enums or a separate class.

Conclusion

Interfaces play a crucial role in Java. They provide abstraction, enable polymorphism, and support multiple inheritance. With default and static methods, they are now more powerful than ever. Use interfaces to write clean, modular, and scalable Java code.

This article was originally published on Medium.

Leave a Comment

Your email address will not be published. Required fields are marked *