Just like a class, Java supports another construct called an interface. Interfaces help to specify the behavior that a class must provide. Java 8 has also made several improvements to Interfaces. This is a two-part article. In part 1 of this article, we will be taking a look at interfaces in their traditional form, and in part 2 of this article, we will be exploring the new features added to interfaces by Java 8.
- What is an Interface
- Defining an Interface
- Implementing an Interface
- Using an Interface
- Extending Interfaces
- Interface fields
What is an Interface
Interfaces encapsulate the behavior of a class. They do this by specifying methods without method bodies (Such methods are known as abstract methods). A class can then implement the interface and provide code for the methods defined in the interface. Thus, they specify what a class must do but leave it to the class to decide how it must do it.
Defining an Interface
Just like the class keyword, Java supports another keyword called interface. This can be used to define an interface. The interface keyword needs to be followed by the name to be given to the interface. Within the interface, you can specify any number of abstract methods. An abstract method is defined by simply specifying the method declaration followed by a semicolon.
Sample Code
public interface ReportGenerator { void generateReport(); void printReport(); }
- This code specifies an interface called ReportGenerator
- Lines 2-3 specify abstract methods generateReport and printReport
Implementing an interface
Once defined, a class can implement the interface. In order to implement an interface, the class name needs to be followed by the implements keyword followed by the interface name. The class that implements the interface needs to provide code for the methods in the interface.
Sample Code
public class PDFReportGenerator implements ReportGenerator { public void generateReport() { System.out.println("Generating PDF report"); } public void printReport() { System.out.println("Printing PDF report"); } }
- This code specifies a class called PDFReportGenerator that implements the ReportGenerator interface
- Lines 3-9 specify code for the generateReport and printReport methods in the ReportGenerator interface. If these methods are not specified, the code will cause a compilation error.
Any number of classes can implement the same interface and provide a different implementation for the methods in the interface.
Sample Code
public class TextReportGenerator implements ReportGenerator { public void generateReport() { System.out.println("Generating text report"); } public void printReport() { System.out.println("Printing text report"); } }
- This code specifies a class called TextReportGenerator that also implements the ReportGenerator interface
- It provides some different implementation for the generateReport and printReport methods
It is possible for a class to implement more than one interfaces. In such cases, the class name needs to be followed by the name of each interface that the class implements. All the interface names need to be separated by commas. Also, the class needs to provide code for the methods in all the interfaces that it implements.
Sample Code
public interface Interface1 { void method1(); void method2(); } public interface Interface2 { void method3(); } public class MyClass implements Interface1, Interface2 { public void method1() { System.out.println("method1"); } public void method2() { System.out.println("method2"); } public void method3() { System.out.println("method3"); } }
- Line 1 defines an interface called Interface1, it has 2 methods, method1 and method2
- Line 5 defines an interface called Interface2, it has a single method called method3
- Line 9 defines a class called MyClass. It implements both Interface1 and Interface2.
- Lines 11-21 provide code for the methods method1, method2 and method3 defined in interfaces Interface1 and Interface2.
Using an Interface
Java does not allow creating an object of the interface since an interface just provides empty methods. You can however create an object of the class that implements the interface.
Sample Code
public class ReportGeneratorDemo { public static void main(String[] args) { PDFReportGenerator r1 = new PDFReportGenerator(); r1.generateReport(); r1.printReport(); TextReportGenerator r2 = new TextReportGenerator(); r2.generateReport(); r2.printReport(); } }
- Earlier, we had created classes called PDFReportGenerator and TextReportGenerator that implement the ReportGenerator interface
- This code specifies a class called ReportGeneratorDemo
- Line 4 creates an object r1 of type PDFReportGenerator
- Lines 5,6 invoke the generateReport and printReport methods on r1
- Similarly, Line 8 creates an object r2 of TextReportGenerator, and Lines 9,10 invoke the generateReport and printReport methods on r2
Output
Generating PDF report
Printing PDF report
Generating text report
Printing text report
You can also assign an object of the class that implements the interface to a variable of the interface type. This helps to achieve runtime polymorphism.
Sample Code
public class ReportGeneratorDemo { public static void main(String[] args) { ReportGenerator r1 = new PDFReportGenerator(); r1.generateReport(); r1.printReport(); r1 = new TextReportGenerator(); r1.generateReport(); r1.printReport(); } }
- Line 4 defines a variable r1 of the interface type that is ReportGenerator but assigns it an object of type PDFReportGenerator
- Lines 5-6 invoke the generateReport and printReport method on r1.
- Since r1 is assigned on the object of type PDFReportGenerator, this results in the methods in the PDFReportGenerator to be invoked
- Line 8 assigns an object of type TextReportGenerator to r1 and Lines 9,10 again invoke generateReport and printReport method on r1.
- In this case, r1 is assigned on the object of type TextReportGenerator, so this results in the methods in the TextReportGenerator to be executed
- Since the same method calls (r1.generateReport and r1.printReport) result in different methods getting invoked and different output being produced, this is an example of runtime polymorphism.
Output
Generating PDF report
Printing PDF report
Generating text report
Printing text report
Extending Interfaces
Just like you can extend a class to create a subclass, it is also possible to extend an interface to create a sub-interface. In order to create a sub-interface, you need to follow the interface name with the extends keyword and the parent interface name. Also, if a class implements the sub-interface, it needs to provide the implementation for the methods in the parent interface as well.
Sample Code
public interface Interface1 { void method1(); void method2(); } public interface Interface2 extends Interface1 { void method3(); } public class MyClass implements Interface2 { public void method1() { System.out.println("method1"); } public void method2() { System.out.println("method2"); } public void method3() { System.out.println("method3"); } }
- Line 1 defines an interface called Interface1, it has 2 methods, method1 and method2
- Line 6 defines an interface called Interface2 which extends Interface1. It has a single method called method3
- Line 10 defines a class called MyClass. It implements Interface2.
- MyClass provides code for the methods in Interface1 and Interface2
Interface fields
In addition to abstract methods, an interface can also contain some fields. By default, the fields declared in an interface are public, static, and final, so they need to be initialized at the time of declaration. A class can access the fields defined in the interface directly via the interface name
Sample Code
public interface Interface1 { int FIELD1=10; double FIELD2=70.75; } public class MyClass implements Interface1 { public void method1() { System.out.println("field1="+Interface1.FIELD1); System.out.println("field2="+Interface1.FIELD2); } }
- Line 1 defines an interface called Interface1
- Line 2 defines an int field called FIELD1 and initializes it to 10
- Line 3 defines a double field called FIELD2 and initializes it to 70.75
- Line 5 specifies a class MyClass that Implements Interface1. It has a method method1 that prints the fields in Interface1
Conclusion
So, in this article, we learned all about Java interfaces. We learned how they help to separate the behavior of a class from its implementation. We saw how to define and implement an interface. We also saw how to implement multiple interfaces and how to extend an interface. Finally, we saw how interfaces help to achieve runtime polymorphism. In part 2 of this article, we will be taking a look at some of the new features added to interfaces by Java 8.