Java 101Future of Interface in Java 9

time to read 4 min | 681 words

Interface is a very popular way to expose our APIs. Until Java 7 it was getting used as a contract (abstract method) where a child class was obliged to implement the contract; but after Java 8, Interface got more power — to where we can have static and default methods.

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:

package id.rezhajulio.test.interfacejava8;

public interface ReportGeneratorJava8 {

    /**

     * Need to get implemented as per ReportGenerator class

     * @param reportData

     * @param schema

     */

    void generateReport(String reportData, String schema);

    /**

     * Get the ready data

     * @param reportSource

     * @return

     * @throws Exception

     */

    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 HtmlReportGeneratorJava8:

package id.rezhajulio.test.interfacejava8;

public class HtmlReportGeneratorJava8 implements ReportGeneratorJava8 {

    @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:

package id.rezhajulio.test.interfacejava9;

public interface ReportGeneratorJava9 {

    /**

     * Need to get implemented as per ReportGenerator class

     * @param reportData

     * @param schema

     */

    void generateReport(String reportData, String schema);

    /**

     * Reading the report data from DB

     * @return

     */

    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

     * @return

     */

    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);

    }

    /**

     * Reading the report data from cache

     * @return

     */

    private String getReportDataFromCache() {

        System.out.println("Reading the data from Cache ....");

        //logic to get the data from Cache

        String reportData = "data from Cache";

        return formatData(reportData);

    }

    /**

     * Formatting the data to create a common standardized data,

     * as it's coming from different systems

     * @param reportData

     * @return

     */

    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

     * @param reportSource

     * @return

     * @throws Exception

     */

    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. Summary of Interface Enhancements

  • Constants (until Java 1.7)

  • Method signatures (until Java 1.7)

  • Nested types (until Java 1.7)

  • Default methods (since 1.8)

  • Static methods (since 1.8)

  • Private methods (since 1.9)

  • Private static methods (since 1.9)

Enjoy the power of Java 9’s Interface.


This is a post in the Java 101 series.
Other posts in this series:

  1. Apr 29, 2017 Translating Scanner tokens into primitive types
  2. Apr 28, 2017 Listing a file system's root directories
  3. Apr 27, 2017 The Console class
  4. Apr 20, 2017 Using an interface as a parameter
  5. Apr 19, 2017 Using bounded type parameters in generic methods
  6. Apr 18, 2017 Using the Deprecated annotation
  7. Apr 17, 2017 Diamond Operator in Java
  8. Apr 15, 2017 Altering format string output by changing a format specifier's argument_index
  9. Apr 13, 2017 Future of Interface in Java 9
  10. Apr 12, 2017 More about Interface in Java 8
  11. Apr 10, 2017 Manage Your JVM Environment with SDKMAN
  12. Apr 09, 2017 Updating interfaces by using default methods
  13. Apr 08, 2017 Converting Stacktrace to String

Related Post:

  1. Apr 29, 2017 Translating Scanner tokens into primitive types
  2. Apr 28, 2017 Listing a file system's root directories
  3. Apr 27, 2017 The Console class
  4. Apr 20, 2017 Using an interface as a parameter
  5. Apr 19, 2017 Using bounded type parameters in generic methods
  6. Apr 18, 2017 Using the Deprecated annotation
  7. Apr 17, 2017 Diamond Operator in Java
  8. Apr 15, 2017 Altering format string output by changing a format specifier's argument_index
  9. Apr 12, 2017 More about Interface in Java 8
  10. Apr 11, 2017 Spring Boot in a Single File
  11. Apr 10, 2017 Manage Your JVM Environment with SDKMAN
  12. Apr 09, 2017 Updating interfaces by using default methods
  13. Apr 08, 2017 Converting Stacktrace to String
  14. Apr 07, 2017 Synchronized Statement in Java
  15. Jul 12, 2016 Fix Java Unsupported major.minor version 52.0 on Ubuntu