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 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();
 }
}
 OUTPUT obtained by running MyInterfaceImpl
 Hello Default
Few points to note about the above program

  • MyInterface implements a default method printHello().
  • Method printHello() is implemented to simply print "Hello Default".
  • MyInterfaceImpl class implements MyInterface
  • In the main method of MyInterfaceImpl when printHello() method is invoked on an instance of MyInterfaceImpl then it calls the default implementation of printHello() and prints "Hello Default"

How are default methods Useful
Default methods are useful in a big way for API designers and indirectly for API implementors. Lets see how. Lets say we define an interface for a group of handheld devices called 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();
}

Now, over a period of time many devices are rolled out and for each new device we implement the 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();
}

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 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();
}
Lets understand how the above code solves our problem

  • isBlueToothEnabled() is the default method. However, it does not contain any implementation.
  • isBlueToothEnabled() by default throws UnsupportedOperationException.
  • Any class which implements DeviceAPI will not be forced with a default implementation if they do not need it. By default, this new operation isBlueToothEnabled() 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.

Default Methods and multiple inheritance
A class can implement multiple interfaces and each of these interfaces can have default methods. Then this becomes an instance of multiple inheritance which was till Java 7 not possible in Java while it was possible in languages such as C++. Multiple inheritance in Java 8 using default methods is a topic on its own and I have written a separate tutorial on it here – multiple inheritance tutorialClick to Read Tutorial on Multiple Inheritance in Java 8.

Summary
This concludes the tutorial on default methods where we understood what are default methods, how we implement default methods in Java 8 interfaces, what kind of a basic design extensibility default methods solve,had a look at making default methods optional and lastly saw that default methods enable multiple inheritance in Java.

 

Digiprove sealCopyright © 2014-2016 JavaBrahman.com, all rights reserved.