Default Methods in Java 8 with examples
This tutorial explains what are default methods in Java 8 with examples, why they are useful and how they can be used to enhance the design of your code.
A little background
Prior to Java 8 interfaces could not have any implemented code. Methods defined in an interface for a type were considered to be the API methods for that type and any classes implementing that API had to implement all the methods. Well, the API part is still true in Java 8 i.e. interfaces will act as APIs for your design. However, interfaces can have implemented code in Java 8. These can be written in 2 ways - static methods & default methods. I have dealt with static methods in a separate articleClick to Read Tutorial on Java 8's Static vs Default Methods. This article will focus on default methods.
What are Default Methods
Default methods are methods implemented in an interface, are non-abstract, and marked by the modifier
OUTPUT obtained by running MyInterfaceImpl
Few points to note about the above program
Now, over a period of time many devices are rolled out and for each new device we implement the
We promptly write a method
The code for
Default methods as optional
To continue with the previous example, our design was good and default methods solved the problem. However, many device vendors complained that their classes were unnecessarily getting this new method
As owners of
Let's understand how the above code solves our problem
default
. These methods are available to all classes which implement this interface.
Format of default methods
Inside an interface we need to mark a default method with the modifier default
as shown in example below -
Interface with a default method
//MyInterface.java
public interface MyInterface{
default void printHello(){
System.out.println("Hello Default");
}
}
//MyInterfaceImpl.java
public class MyInterfaceImpl implements MyInterface{
public static void main(String args[]){
new MyInterfaceImpl().printHello();
}
}
Hello Default
MyInterface
implements a default methodprintHello()
.- Method
printHello()
is implemented to simply print"Hello Default"
. MyInterfaceImpl
class implementsMyInterface
- In the main method of
MyInterfaceImpl
whenprintHello()
method is invoked on an instance ofMyInterfaceImpl
then it calls the default implementation ofprintHello()
and prints"Hello Default"
DeviceAPI
. It has methods like getOS()
, getMaxResolution()
and getBrand()
- all abstract. Our interface DeviceAPI
would then look like this - DeviceAPI.java
public interface DeviceAPI{
public String getOS();
public String getMaxResolution();
public String getBrand();
}
DeviceAPI
interface and hence, we also implement all the abstract methods. Its all going fine when we come to know that a wearable device has come out which needs to have a check for whether bluetooth is enabled on the device.We promptly write a method
isBlueToothEnabled()
in the interface DeviceAPI
. But then we notice that DeviceAPI
has had more than a few, infact 20-30 implementations, many of these implementations were done by device vendors using this API and we have no access to their source code. If we go ahead and add this new method isBlueToothEnabled()
to DeviceAPI
, everything will be fine for the vendors till they do not recompile their implementation class along with the new DeviceAPI
. Then their code will start failing as compiler will not find the new method in their implementation. Secondly, we will have to change all of the 20-30 implementations. Even though that device maybe a wearable type of device or not.
How to overcome the issue of adding a new functionality to the API without breaking the code
Till Java 7 this kind of new functionality was very difficult to introduce due to the problems we noted above. But in Java 8 we have a solution for this. We can implement this isBlueToothEnabled()
method as a default method in DeviceAPI
. This implementation will then automatically be available to all the classes which implement DeviceAPI
.The code for
DeviceAPI
with the default method would look like this - DeviceAPI.java with default method
public interface DeviceAPI{
default boolean isBlueToothEnabled(){
//default method implementation goes here
}
public String getOS();
public String getMaxResolution();
public String getBrand();
}
isBlueToothEnabled()
. Vendors complain to us that their maintenance engineers may end up using this method as they might miss reading the documentation around this method. Basically, vendors want this method to be available if they need it, else they do not want to support this method for their devices.As owners of
DeviceAPI
we then tweak the default implementation of isBlueToothEnabled()
method to the one shown below - DeviceAPI.java with default method made optional to inherit
public interface DeviceAPI{
default boolean isBlueToothEnabled(){
throw new UnsupportedOperationException();
}
public String getOS();
public String getMaxResolution();
public String getBrand();
}
isBlueToothEnabled()
is the default method. However, it does not contain any implementation.isBlueToothEnabled()
by default throwsUnsupportedOperationException
.- Any class which implements
DeviceAPI
will not be forced with a default implementation if they do not need it. By default, this new operationisBlueToothEnabled()
will be unsupported. - Only when an implementation class really needs the
isBlueToothEnabled()
method they will override this method and write their own version - A default method written in the above way thus becomes optional.