An interface is a Java construct that functions like an implicit abstract class. In Java, a derived class can extend the behavior of only one class, but it can implement as many interfaces as it requires.
The purpose of an interface is to provide a specification for a set of public interface methods. An interface declaration introduces a new data type, just as a class declaration and definition does.
Java interfaces can only contain four types of members. These include:
Constant Fields — All interface fields are implicitly public, static, and final
Abstract Methods — All interface methods are implicitly public and abstract
Nested Class Declarations — These are implicitly public and static
Nested Interface Declarations — These have the same characteristics as interfaces!
Table 11-1 summarizes the differences between abstract classes and interfaces.
Abstract Class | Interface |
---|---|
Must be declared to be abstract with the abstract keyword. | Is implicitly abstract and the use of the abstract keyword is discouraged in an interface declaration. |
Can contain abstract as well as concrete methods. The concrete methods can be public, private, or protected. | Can only contain abstract methods. All methods in an interface are implicitly public and abstract. Redundantly declaring interface methods to be public and abstract is permitted but discouraged. |
Can contain public, private, and protected variable data fields and constants. | Can only contain public constant fields. All fields in an interface are implicitly public, static, and final. Redundantly declaring an interface field to be public, static, and final is allowed but discouraged. |
Can contain nested class and interface declarations. | Can contain nested class and interface declarations. These inner class and interface declarations are implicitly public and static. |
Can extend one class but implement many interfaces. | Can extend many interfaces. |
Interfaces are expressed in the UML in two ways as is shown in figure 11-13.
Figure 11-13: Two Types of UML Interface Diagrams
One way to show an interface in the UML is with a simple circle with the name of the interface close by. The second way involves the use of an ordinary class diagram that includes the stereotype << interface >>. Each of these diagrams, the circle and the class diagram, can be used to represent the use of interfaces in an inheritance hierarchy as is discussed in the following section.
When a class implements an interface it is said to be realizing the interface. Interface realization is expressed in the UML in two distinct forms: 1) the simple form where the circle is used to represent the interface and is combined with an association line to create a lollipop diagram, or 2) the expanded form where an ordinary class diagram is used to represent the interface. Figure 11-14 illustrates the use of the lollipop diagram to convey the simple form of realization and figure 11-15 shows an example of the expanded form of realization.
Figure 11-14: UML Diagram Showing the Simple Form of Realization
Figure 11-15: UML Diagram Showing the Expanded Form of Realization
Let’s turn our attention to a simple example of an interface in action. Figure 11-16 gives the UML diagram of the interface named MessagePrinter and a class named MessagePrinterClass that implements the MessagePrinter interface. The source code for these two classes is given in examples 11.12 and 11.13.
Figure 11-16: UML Diagram Showing the MessagePrinterClass Realizing the MessagePrinter Interface
Example 11.12: MessagePrinter.java
1 interface MessagePrinter { 2 void printMessage(); 3 void setMessage(String message); 4 }
Example 11.13: MessagePrinterClass.java
1 public class MessagePrinterClass implements MessagePrinter { 2 private String _message = null; 3 4 public MessagePrinterClass(String message){ 5 _message = message; 6 } 7 8 public MessagePrinterClass(){ 9 this("Default message is boring!"); 10 } 11 12 public void printMessage(){ 13 System.out.println(_message); 14 } 15 16 public void setMessage(String message){ 17 _message = message; 18 } 19 }
As you can see from example 11.12 the MessagePrinter interface is short and simple. All it does is declare the two interface methods printMessage() and setMessage(). The implementation of these interface methods is left to any class that implements the MessagePrinter interface as the MessagePrinterClass does in example 11.13.
Example 11.14 gives the test driver program for this example. As you can see on line 3 you can declare an interface type reference. I called this one mp1. Although you cannot instantiate an interface directly with the new operator you can initialize an interface type reference to point to an object of any concrete class that implements the interface. The only methods you can call on the object via the interface type reference are those methods specified by the interface. You could of course cast to a different type if required but you must strive to minimize the need to cast in this manner.
Example 11.14: DriverApplication.java
1 public class DriverApplication { 2 public static void main(String[] args){ 3 MessagePrinter mp1 = new MessagePrinterClass("Interfaces are cool!" + 4 " Heh, heh, aren't they Butthead?"); 5 MessagePrinterClass mpc1 = new MessagePrinterClass("Shut up Beavis!"); 6 7 mp1.printMessage(); 8 mpc1.printMessage(); 9 } 10 }
Figure 11-17 gives the results of running example 11.14.
Figure 11-17: Results of Running Example 11.14
The purpose of an interface is to specify a set of public interface methods. Interfaces can have four types of members: 1) constants, 2) abstract methods, 3) nested classes, and 4) nested interfaces. Classes can inherit from or extend only one other class, but they can implement as many interfaces as are required. Interfaces can extend as many other interfaces as necessary.