Interface in Java: Explained (Including Java 8 and 9 updates)

In this blog post we’ll cover what is an interface in Java. We have also included the updates that came along with Java 8 and 9.

What is interface in Java?

Interface in Java is a reference type, similarly to classes. To refresh your mind, reference type is a data type that is based on a class. This class could be part of the Java API or you might have written it yourself.

Interface is sort of a contract for classes that implement it. It dictates how the implementing classes should behave. This is achieved by declaring abstract methods in the interface. When a class implements an interface in Java, it has to implement all the abstract methods of the interface. In addition, interfaces are also used to hide implementation details from the users of it. We could say that it acts as a public API of a certain type.

Following is what we can define in an interface:

  • Constants (static final variables)
  • Abstract methods
  • Default methods
  • Static methods
  • Private methods

All the constants and methods, excluding private methods, are public by default. To point out, you don’t explicitly need to define that a method is public. We’ll see that shortly in our example code. In addition to that, an interface can’t be instantiated. On a more positive note, classes can implement multiple interfaces at a time and interfaces can extend multiple interfaces if needed.

To make it all more clear lets’ first take a look at a simple interface example where we define an abstract method. After that, we’ll dive into the different kinds of methods an interface can have.

Java interface example

First, we’ll define our interface Animal and add a class Cat that will implement the Animal interface. Within Animal we’ll also define an abstract method called makeSound.

public interface Animal {
    // This is actually a public abstract method
    void makeSound();
}
public class Cat implements Animal {

    @Override
    public void makeSound() {
        System.out.println("Meow");
    }
}

As you can see the makeSound method doesn’t have a body in the Animal interface because it is abstract. Therefore, we had to add a concrete implementation of it in the Cat class.

Next, we’ll create an instance of the Cat class and call the makeSound method. Note how we reference to the Animal interface even though we create an instance of a Cat.

Animal cat = new Cat();
cat.makeSound();

Output:

Meow

Default methods in interfaces

Support for default methods in Java interfaces came along in Java 8. They help to provide some default functionality that implementing classes can use or override. The most important thing to note is that they won’t break the already implementing classes because default methods are not abstract. Backwards compatibility is also the main point why they were introduced to the interfaces in Java. Note, default methods are public by default.

This is how you add a default method drink to our already existing Animal interface.

public interface Animal {

    void makeSound();

    default void drink() {
        System.out.println("Drinking water");
    }
}

The drink method is now available to all the implementing classes without breaking them. In our case for the Cat class. Note, nothing has changed in the Cat class.

Now all we need to do is to call the drink method by using an instance of the Cat class.

cat.drink();

Output:

Drinking water

When needed, we can also override a default method drink in the implementing class to provide custom behaviour.

public class Cat implements Animal {

    @Override
    public void makeSound() {
        System.out.println("Meow");
    }

    @Override
    public void drink() {
        System.out.println("Drinking milk");
    }
}

When we now call out the drink method on our Cat object the output would look like this:

Drinking milk

Static methods in interfaces

Static methods in interfaces were introduced in Java 8. They are similar to static methods in classes and are great for defining utility methods. Static methods don’t belong to a concrete object as they are part of the interface itself. Therefore, to call a method, we need to use an interface name followed by the static method name (<InterfaceName>.<staticMethodName>()). In addition to that, they are public by default.

If you so far have used utility classes (classes with only static methods in it) in your codebase and every time need to make sure they are not instantiated, you can now switch over to using utility interfaces instead. As we already mentioned before, interfaces cannot be instantiated. Therefore our code becomes cleaner and easier to read.

Defining a static method is similar to defining a static method in a class. In addition, static methods can be called from other static methods or even from default methods.

To see a static method in action, lets’ modify our already existing Animal interface.

public interface Animal {

    void makeSound();

    default void drink() {
        System.out.println("Drinking water");
    }

    static Optional<String> findAnimalBySound(String sound) {
        if (sound.equals("meow")) {
            return Optional.of("cat");
        }

        return Optional.empty();
    }
}

Here we defined a new static method findAnimalBySound that takes in a string named sound and returns an optional of an animal that makes the sound. If the animal to the given sound doesn’t exist, we return an empty optional instead and let the caller of this method to decide what to do with it.

As a final step, lets’ also call our static method and see the output:

// Find animal by sound. If it doesn't exist, set the animal to unknown
String animal = Animal.findAnimalBySound("meow").orElse("unknown");
System.out.println(animal);

Output:

cat

Private methods in interfaces

From Java 9 we can define private methods in interfaces. This is a wonderful feature to keep your interfaces code more readable and duplicate-free.

As an example lets’ add a very simple private method getCat to our already existing Animal interface. This method is called from the findAnimalBySound method.

public interface Animal {

    void makeSound();

    default void drink() {
        System.out.println("Drinking water");
    }

    static Optional<String> findAnimalBySound(String sound) {
        if (sound.equals("meow")) {
            String cat = getCat();
            return Optional.of(cat);
        }

        return Optional.empty();
    }

    private static String getCat() {
        return "cat";
    }

}

Conclusion

Interface in Java is a reference type. It defines how its’ implementing classes should behave. Furthermore, it hides the implementation details from its’ clients. In Java interfaces we can define constants and various types of methods: abstract, default, static and private. These are all public by default, except the private methods.

Be the first to reply

Leave a Reply

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