Why interface is changed in java 8 and java 9?

What is interface?

Interface looks like a class but it is not a class. An interface can have methods and variables just like the class but the methods declared in interface are by default abstract (only method signature, no body, see: Java abstract method). Also, the variables declared in an interface are public, static & final by default.

Real Life Example:

A remote control is a type of interface, you deal with the buttons to operate it, you have no idea what kind of implementation it is hiding.



Marker or tag interface:

An empty interface is known as tag or marker interface. For example Serializable, EventListener, Remote(java.rmi.Remote) are tag interfaces, there are few other tag interfaces as well.
These interfaces do not have any field and methods in it. You must be thinking if they are empty why class implements them? What’s the use of it? Class implements them to claim the membership in a particular set. For example: If a class implements Serializable interface, it is claiming to be the member of Serializable classes, so if JVM (Java Virtual Machine) sees that a class is Serializable, it does some trick or special operation that helps in the serialization/de-serialization process.

Interface changes in Java 8:

Oracle Corporation has introduced some new features to interface in Java 8 Release. That is Default methods and Static methods feature.
Yes, we can write method implementations in Interface from Java 8 onwards. We need to use default keyword to define them as shown below.

In Java 8, an interface can have only four kinds of things:
  1. Constant variables
  2. Abstract methods
  3. Default methods
  4. Static methods

Default and Static methods were added in Java8.

Why default method?

For example, if several classes such as A, B, C and D implements an interface XYZInterface then if we add a new method to the XYZInterface, we have to change the code in all the classes(A, B, C and D) that implements this interface. In this example we have only four classes that implements the interface which we want to change but imagine if there are hundreds of classes implementing an interface then it would be almost impossible to change the code in all those classes. 
This is why in java 8, we have a new concept “default methods”. These methods can be added to any existing interface and we do not need to implement these methods in the implementation classes mandatory, thus we can add these default methods to existing interfaces without breaking the code.

Static methods in interfaces are similar to the default methods except that we cannot override these methods in the classes that implements these interfaces.

Java 8 Example: Default method in Interface:
The method newMethod() in JavaInterfaceDefaultMethod is a default method, which means we need not to implement this method in the implementation class Example. This way we can add the default methods to existing interfaces without bothering about the classes that implements these interfaces.

interface JavaInterfaceDefaultMethod{  
    /* This is a default method so we need not to implement this method in the implementation classes.*/
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    /* Already existing public and abstract method We must need to implement this method in implementation classes.*/
    void existingMethod(String str);  
}  
public class Example implements JavaInterfaceDefaultMethod{ 
// implementing abstract method
    public void existingMethod(String str){           
        System.out.println("String is: "+str);  
    }  
    public static void main(String[] args) {  
    Example obj = new Example();
    //calling the default method of interface
        obj.newMethod();     
        //calling the abstract method of interface
        obj.existingMethod("Java 8 is easy to learn"); 
      }  
}
Output:
Newly added default method
String is: Java 8 is easy to learn
Java 8 Example: Static method in Interface:
As mentioned above, the static methods in interface are similar to default method so we need not to implement them in the implementation classes. We can safely add them to the existing interfaces without changing the code in the implementation classes. Since these methods are static, we cannot override them in the implementation classes.
interface JavaInterfaceDefaultMethod{  
    /* This is a default method so we need not to implement this method in the implementation classes.*/
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    
    /* This is a static method. Static method in interface is similar to default method except that we cannot override  them in the implementation classes. Similar to default methods, we need to implement these methods
     * in implementation classes so we can safely add them to the  existing interfaces.
     */
    static void anotherNewMethod(){
    System.out.println("Newly added static method");
    }
    /* Already existing public and abstract method We must need to implement this method in implementation classes.*/
    void existingMethod(String str);  
}  
public class Example implements JavaInterfaceDefaultMethod

// implementing abstract method
    public void existingMethod(String str){           
        System.out.println("String is: "+str);  
    }  
    public static void main(String[] args) {  
    Example obj = new Example();
   
    //calling the default method of interface
        obj.newMethod();     
        //calling the static method of interface
        MyInterface.anotherNewMethod();
        //calling the abstract method of interface
        obj.existingMethod("Java 8 is easy to learn");      
    }  
}
Output:
Newly added default method
Newly added static method
String is: Java 8 is easy to learn
Java 8 – Abstract classes vs interfaces:
With the introduction of default methods in interfaces, it seems that the abstract classes are same as interface in java 8. However this is not entirely true, even though we can now have concrete methods(methods with body) in interfaces just like abstract class, this doesn’t mean that they are same. There are still few differences between them, one of them is that abstract class can have constructor while in interfaces we can’t have constructors.

Interface changes in Java 9:
In Java 9, Interface is getting more power, to the point where we can define private methods as well. Let us understand why we need private methods in Interfaces.
Suppose we are defining a ReportGenerator Interface in Java8 as below:
public interface ReportGeneratorInterfaceJava8 {
    /** Need to get implemented as per ReportGenerator class */
    void generateReport(String reportData, String schema);
    
    default String getReportData(String reportSource) throws Exception {
        String reportData = null;
        if (null == reportSource) {
            throw new Exception("reportSource can't be null....");
        }
        if (reportSource.equalsIgnoreCase("DB")) {
            System.out.println("Reading the data from DB ....");
            //logic to get the data from DB
            reportData = "data from DB";
        } else if (reportSource.equalsIgnoreCase("File")) {
            System.out.println("Reading the data from FileSystem ....");
            //logic to get the data from File
            reportData = "data from File";
        } else if (reportSource.equalsIgnoreCase("Cache")) {
            System.out.println("Reading the data from Cache ....");
            //logic to get the data from Cache
            reportData = "data from Cache";
        }
        System.out.println("Formatting the data to create a common standard");
        /** Format the data and then return **/
        //logic to format the data
        return reportData;
    }
}
And the implementation class could be XMLReportGeneratorJava8:

public class XMLReportGeneratorJava8 implements ReportGeneratorInterfaceJava8 {
    @Override
    public void generateReport(String reportData, String schema) {
        //HTML Specific Implementation according to given schema
    }
}

Method 'getReportData' looks pretty messy, as there is a lot of logic that could be kept in a separate method and that can be called in 'getReportData'. To achieve that, we need a private method, as we don't want to expose these methods to outside the world.
Another thing, ReportGeneratorJava8 interface is formatting the data after getting it from the source. So we can have a common method named 'formatData' defined as private in the interface.  So the interface could be rewritten as below:
public interface ReportGeneratorJava9 {
    void generateReport(String reportData, String schema);
    /** Reading the report data from DB*/
    private String getReportDataFromDB() {
        System.out.println("Reading the data from DB ....");
        //logic to get the data from DB
        String reportData = "data from DB";
        return formatData(reportData);
    }
    /**Reading the report data from FileSystem*/
    private String getReportDataFromFile() {
        System.out.println("Reading the data from FileSystem ....");
        //logic to get the data from File
        String reportData = "data from File";
        return formatData(reportData);
    }
    /** Formatting the data to create a common standardized data, as it's coming from different systems*/
    private String formatData(String reportData) {
        System.out.println("Formatting the data to create a common standard");
        /** Format the data and then return **/
        //logic to format the data
        return reportData;
    }
    /** Get the ready data*/
    default String getReportData(String reportSource) throws Exception {
        String reportData = null;
        if (null == reportSource) {
            throw new Exception("reportSource can't be null....");
        }
        if (reportSource.equalsIgnoreCase("DB")) {
            reportData = getReportDataFromDB();
        } else if (reportSource.equalsIgnoreCase("File")) {
            reportData = getReportDataFromFile();
        } else if (reportSource.equalsIgnoreCase("Cache")) {
            reportData = getReportDataFromCache();
        }
        return reportData;
    }
}
Now the above implementation looks pretty clean, and we've seen the need of private methods in Interface.

Comments