Java 8 New Features: Default Method

Following the last article about Lambda feature in Java 8, I spent some more time on other features and will blog about them along the way. It’s a good way to push me to really think through and thus deepen my understanding. This article is about default method which is in fact related to the lambda feature.

The Problem
As discussed in the last article, the lambda feature simplifies the function code. One of the most useful applications is the existing Java collection API. You can use lambda to sort, filter, transform the collections. For that, the interfaces need to be changed to include new methods. But any new addition to an existing interface would break all the implementer classes. What’s the big deal to change the implementer classes? It’s not hard for the implementer classes within your control, for example, you can change ArrayList based on the change on List interface. But it’s impossible for other classes outside of your control. For that compatibility, default method was invented as a smart hack.

Bothered by SLOW Web UI to manage vSphere? Want to manage ALL your VMware vCenters, AWS, Azure, Openstack, container behind a SINGLE pane of glass? Want to search, analyze, report, visualize VMs, hosts, networks, datastores, events as easily as Google the Web? Find out more about vSearch 3.0: the search engine for all your private and public clouds.

The default methods are the methods defined in interface with default keyword and come with implementation. You can choose to override the implementation. But if not, the default implementation is used. In so doing, the previous implementer classes won’t break.

It may be a bit abstract. Let’s take a look at an example.

package org.doublecloud.jave8demo.defaultmethod;
 
public class CloudServerDemo
{
  public static void main(String[] args)
  {
    DoubleClouder dc = new DoubleClouder();
    dc.startServer("doublecloud-001");
    // do something with the machine before stopping it
    dc.stopServer("doublecloud-001");
  }
}
 
class DoubleClouder implements CloudService
{
  @Override
  public void startServer(String name)
  {
    System.out.println("Starting " + name);
  }
 
  @Override
  public void stopServer(String name)
  {
    System.out.println("Stopping " + name);
  }
}
 
package org.doublecloud.jave8demo.defaultmethod;
 
public interface CloudService
{
  void startServer(String name);
  void stopServer(String name);
}

The CloudService interface has two methods that start and stop a server. The service is implemented by the DoubleClouder class. Because it’s just a sample to illustrate default method, the methods just print out console messages. The CloudService interface is shipped outside and implemented by other vendors, say Amazon, Microsoft.

Later we decide to add a new method say suspendServer() to the CloudService interface. I can easily change DoubleClouder because it’s in my control. But the Amazon, Microsoft’s code will break with the evolved interface.

The Solution

To avoid the compatibility issue, the default method feature comes to save. Here is the code showing how to do it.

package org.doublecloud.jave8demo.defaultmethod.evolved;
 
public class CloudServerDemo
{
  public static void main(String[] args)
  {
    DoubleClouder dc = new DoubleClouder();
    dc.startServer("doublecloud-001");
    // do something with the machine before stopping it
 
    // to suspend the cloud machine, call following
    // dc.suspendServer("doublecloud-001");
 
    dc.stopServer("doublecloud-001");
  }
}
 
class DoubleClouder implements CloudService
{
  @Override
  public void startServer(String name)
  {
    System.out.println("Starting " + name);
  }
 
  @Override
  public void stopServer(String name)
  {
    System.out.println("Stopping " + name);
  }
}
 
package org.doublecloud.jave8demo.defaultmethod;
 
public interface CloudService
{
  void startServer(String name);
  void stopServer(String name);
  default void suspendServer(String name) 
  { 
    System.out.println("Suspending " + name); 
  }
}

As you can see, the implementer class DoubleClouder does not need to make any change. So do other implementer classes that I don’t even know of. With this trick, the compatibility problem is solved nicely.

Note that, the default methods in some way are hacks that handles evolved interfaces. They should not be used as a normal way for providing implementations. In the version 1.0 of an API, you should probably not expect to see these default methods in interfaces. There are exceptions of course and I’ll discuss the details in the end.

Is Interface Now the Same as Abstract Class

On one hand, the default implementation make the interface behave like abstract class. On the other hand, there are still key differences between new interface with default methods and abstract class:

1. A class can inherit only one class but can implement many interfaces. However, with the default methods there are potential conflicts among different implementations, like what could happen with multiple inheritance in C++. For nicely designed interfaces, it’s not likely to have this problem.

2. An interface with default method can still not have any property while abstract class can. Because of this, the interface cannot memorize anything.

With the above two points in mind, the default method is just a simple trick or hack for Java back compatibility. It does not change the fundamental difference between interface and abstract class.

When Should We Use Default Methods

Given why default method was added into Java 8, one obvious use case is to handle back compatibility. In Java 8 standard library, we can find plenty of samples, especially in the collection library. If you also do have to evolve an existing interface, default methods is a powerful tool.

There is another use case for interfaces on which we want to apply lambda. Remember the requirement for lambda on an interface – there is only one method. The default methods are not counted and cannot be used with lambda expression neither. But they allow an interface with multiple methods to keep one method for lambda. Looking for an example, check out the IntConsumer interface which has a default method andThen(IntConsumer after) and a normal method accept(int value).

This entry was posted in Software Development and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  • NEED HELP?


    My company has created products like vSearch ("Super vCenter"), vijavaNG APIs, EAM APIs, ICE tool. We also help clients with virtualization and cloud computing on customized development, training. Should you, or someone you know, need these products and services, please feel free to contact me: steve __AT__ doublecloud.org.

    Me: Steve Jin, VMware vExpert who authored the VMware VI and vSphere SDK by Prentice Hall, and created the de factor open source vSphere Java API while working at VMware engineering. Companies like Cisco, EMC, NetApp, HP, Dell, VMware, are among the users of the API and other tools I developed for their products, internal IT orchestration, and test automation.