Guide to Java Interface


This guide walks you through how to create interfaces in real projects, using java 8 static and default methods in java projects.
As we know, In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces.
To compile and run examples from this guide, you need to install JDK 8.

Basics of Interface

Using the keyword interface, you can fully abstract a class’ interface from its implementation. That is using interface, you can specify what a class must do, but not how it does it.
From Java 8 onwards we can define the implementation of default and static methods in an interface. In Java 9 we can define private methods.
Before using interfaces it's important to know why we need to use interfaces in Java.
There are mainly three reasons to use interface. They are given below.
  • It is used to achieve abstraction.
  • By interface, we can support the functionality of multiple inheritance.
  • It can be used to achieve loose coupling. Understanding relationship between classes and interfaces via diagram and multiple inheritance in Java by Interface Diagram here Code for interface not for implementation
Interfaces are just contracts or signatures and they don't know anything about implementations. Java 8 brought to the table a few brand new features, including lambda expressions, functional interfaces, method references, streams, Optional, and static and default methods in interfaces.

Rules for creating an interface

The following is a list of rules for creating an interface, many of which you should recognize as adaptions of the rules for defining abstract classes.

1. Interfaces cannot be instantiated directly.

2. An interface is not required to have any methods.

3. An interface may not be marked as final.

4. All top-level interfaces are assumed to have public or default access, and they must include the abstract modifier in their definition. Therefore, marking an interface as private, protected, or final will trigger a compiler error, since this is incompatible with these assumptions.

5. All non default methods in an interface are assumed to have the modifiers abstract and public in their definition. 

Therefore, marking a method as private, protected, or final will trigger compiler errors as these are incompatible with the abstract and public keywords.

There are two inheritance rules you should keep in mind when extending an interface

1. An interface that extends another interface, as well as an abstract class that implements an interface, inherits all of the abstract methods as its own abstract methods.

2. The first concrete class that implements an interface, or extends an abstract class that implements an interface, must provide an implementation for all of the inherited abstract methods.

Default Method in Interface

Why Default Methods in Interfaces Are Needed

  • Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
  • In a typical design based on abstractions, where an interface has one or multiple implementations, if one or more methods are added to the interface, all the implementations will be forced to implement them too. Otherwise, the design will just break down so default interface methods are an efficient way to deal with this issue. They allow us to add new methods to an interface that are automatically available in the implementations. Thus, there’s no need to modify the implementing classes. In this way, backward compatibility is neatly preserved without having to refactor the implementers.
  • The default method is used to define a method with default implementation. You can override default method also to provide the more specific implementation for the method.

The default interface method rules

The following are the default interface method rules you need to be familiar with:

1. A default method may only be declared within an interface and not within a class or abstract class.


2. A default method must be marked with the default keyword. If a method is marked as default, it must provide a method body.


3. A default method is not assumed to be static, final, or abstract, as it may be used or overridden by a class that implements the interface.


4. Like all methods in an interface, a default method is assumed to be public and will not compile if marked as private or protected.

Examples of default methods

To better understand the functionality of default interface methods, let’s create a simple example.
Step 1: Creare Vehicle interface and just one implementation. Let's first discuss just one implementation of default methods of Vehicle interface.
public interface Vehicle {
 String getBrand();

 String speedUp();

 String slowDown();

 default String turnAlarmOn() {
  return "Turning the vehice alarm on.";
 }

 default String turnAlarmOff() {
  return "Turning the vehicle alarm off.";
 }

 static int getHorsePower(int rpm, int torque) {
  return (rpm * torque) / 5252;
 }
}
Step 2: let’s write the implementing class for Vehicle interface.
public class Car implements Vehicle {

    private final String brand;

    public Car(String brand) {
        this.brand = brand;
    }

    @Override
    public String getBrand() {
        return brand;
    }

    @Override
    public String speedUp() {
        return "The car is speeding up.";
    }

    @Override
    public String slowDown() {
        return "The car is slowing down.";
    }
}
Step 3: Let's test the above implementation with main() method.
Please notice how the default methods turnAlarmOn() and turnAlarmOff() from our Vehicleinterface are automatically available in the Car class.
public class TestJava8Interface {
 public static void main(String[] args) {

  Vehicle car = new Car("BMW");
  System.out.println(car.getBrand());
  System.out.println(car.speedUp());
  System.out.println(car.slowDown());
  System.out.println(car.turnAlarmOn());
  System.out.println(car.turnAlarmOff());
  System.out.println(Vehicle.getHorsePower(2500, 480));
  
 }
}
Output :
BMW The car is speeding up.
The car is slowing down.
Turning the vehice alarm on.
Turning the vehicle alarm off.
228
Now, we write two implementations for Vehicle interface and test the default methods behavior. Let's create Motorbike class which implements Vehicle interface.
public class Motorbike implements Vehicle {

    private final String brand;

    public Motorbike(String brand) {
        this.brand = brand;
    }

    @Override
    public String getBrand() {
        return brand;
    }

    @Override
    public String speedUp() {
        return "The motorbike is speeding up.";
    }

    @Override
    public String slowDown() {
        return "The motorbike is slowing down.";
    }
}
Let's test the two implementations for Vehicle interface with main() method.
The most typical use of default methods in interfaces is to incrementally provide additional functionality to a given type without breaking down the implementing classes.
public class TestJava8Interface {
 public static void main(String[] args) {

  Vehicle car = new Car("BMW");
  System.out.println(car.getBrand());
  System.out.println(car.speedUp());
  System.out.println(car.slowDown());
  System.out.println(car.turnAlarmOn());
  System.out.println(car.turnAlarmOff());
  System.out.println(Vehicle.getHorsePower(2500, 480));
  
  Vehicle bike = new Motorbike("ACTIVA 4G");
  System.out.println(bike.getBrand());
  System.out.println(bike.speedUp());
  System.out.println(bike.slowDown());
  System.out.println(bike.turnAlarmOn());
  System.out.println(bike.turnAlarmOff());
  System.out.println(Vehicle.getHorsePower(2500, 480));
  
 }
}
Multiple Interface Inheritance Rules
We know that Java allows classes to implement multiple interfaces, it’s important to know what happens when a class implements several interfaces that define the same default methods.
To better understand this scenario, let’s define a new Alarm interface.
public interface Alarm {
 default String turnAlarmOn() {
  return "Turning the alarm on.";
 }

 default String turnAlarmOff() {
  return "Turning the alarm off.";
 }
}
Now, let Car class implement two interfaces Vehicle and Alaram. The source code for same is
public class MultiAlarmCar implements Vehicle, Alarm {

    private final String brand;

    public MultiAlarmCar(String brand) {
        this.brand = brand;
    }

    @Override
    public String getBrand() {
        return brand;
    }

    @Override
    public String speedUp() {
        return "The motorbike is speeding up.";
    }

    @Override
    public String slowDown() {
        return "The mootorbike is slowing down.";
    }

}
In this case, the compiler reports an error like Duplicate default methods named turnAlarmOffwith the parameters () inherited from the types Alarm and Vehicle
To solve this ambiguity, we must explicitly provide an implementation for the methods:
@Override
public String turnAlarmOn() {
    // custom implementation
}
     
@Override
public String turnAlarmOff() {
    // custom implementation
}
We can also have our class use the default methods of one of the interfaces.
Let’s see an example that uses the default methods from the Vehicle interface:
@Override
public String turnAlarmOn() {
    return Vehicle.super.turnAlarmOn();
}
 
@Override
public String turnAlarmOff() {
    return Vehicle.super.turnAlarmOff();
}
Similarly, we can have the class use the default methods defined within the Alarm interface:
@Override
public String turnAlarmOn() {
    return Alarm.super.turnAlarmOn();
}
 
@Override
public String turnAlarmOff() {
    return Alarm.super.turnAlarmOff();
}
Furthermore, it’s even possible to make the Car class use both sets of default methods:
@Override
public String turnAlarmOn() {
    return Vehicle.super.turnAlarmOn() + " " + Alarm.super.turnAlarmOn();
}
     
@Override
public String turnAlarmOff() {
    return Vehicle.super.turnAlarmOff() + " " + Alarm.super.turnAlarmOff();
}

Static Method in Interface

Generally, static methods are used to define utility methods.
The idea behind static interface methods is to provide a simple mechanism that allows us to increase the degree of cohesion of a design by putting together related methods in one single place without having to create an object.
Furthermore, static methods in interfaces make possible to group related utility methods, without having to create artificial utility classes that are simply placeholders for static methods.

The static interface method rules

Here are the static interface method rules you need to be familiar with:

1. Like all methods in an interface, a static method is assumed to be public and will not compile if marked as private or protected.


2. To reference the static method, a reference to the name of the interface must be used.
Example of a static method in Interface
public interface Vehicle {
 String getBrand();

 String speedUp();

 String slowDown();

 default String turnAlarmOn() {
  return "Turning the vehice alarm on.";
 }

 default String turnAlarmOff() {
  return "Turning the vehicle alarm off.";
 }

 static int getHorsePower(int rpm, int torque) {
  return (rpm * torque) / 5252;
 }
}
There is getHorsePower(int, int) static method in Vehicle interface.
Let's see how the client uses this method :
public class TestJava8Interface {
 public static void main(String[] args) {

  Vehicle car = new Car("BMW");
  System.out.println(car.getBrand());
  System.out.println(car.speedUp());
  System.out.println(car.slowDown());
  System.out.println(car.turnAlarmOn());
  System.out.println(car.turnAlarmOff());
  System.out.println(Vehicle.getHorsePower(2500, 480));
 }
}

Summary

  • We can’t create an instance(interface can’t be instantiated) of an interface but we can make reference to it that refers to the Object of its implementing class.
  • A class can implement more than one interface.
  • An interface can extends another interface or interfaces (more than one interface) .
  • A class that implements interface must implements all the methods in interface.
  • All the methods are public and abstract. And all the fields are public, static, and final.
  • It is used to achieve multiple inheritance.
  • It is used to achieve loose coupling.
  • From Java 8 onwards Interface can contain static and default methods. In Java 9 Interface contains private methods.


Comments