Static and Default Methods in Interface – Java 8

Introduction

Java 8 introduces concept of “Default Methods” and “Static Methods” for interfaces, which allows developers to enhance existing interface used in their applications without breaking prior implementations of that interface. “Default Methods” and “Static Methods” are one of new features of Java 8 which is used extensively in core Java framework packages especially in collections.

Benefit of “Default Methods” and “Static Methods”

This feature is very controversial. It apparently seems to be making the abstract classes and interfaces quite similar. And also introduces the problems of multiple inheritance as a class can implement multiple interfaces with same default method signature.

Well Developers at oracle tried to simplify things. They want to have all related methods at one place instead of having separate base utility class for interface and then other classes extend that class and overrides applicable methods. Another reason is they want to enhance core framework to support new features like lambda expressions, Stream API without breaking millions of lines of code.

With this approach, developers can add new default methods and static methods to interface and they don’t need to change all implementing classes of it.

Default Methods

“Default Methods” is defined with body in an interface and indicated by modifier default. As its name suggests these methods are available to all classes who implements an interface. Please note that Default methods are public by default like other methods declared in an interface, so no need to specify public on it.

public interface BankCustomer {
 // Abstract methods
 Customer getCustomer(String id);
 void setCustomer(String id);
 //default method
 default String getAccountInfo(String id) {
 // return account info of customer
 }
}

In an above example we have two abstract methods like an old interface and one default method with its body. If you try to just declare default method without its body then it will throw compilation error. Now all implementation classes can decide to override this method or just ignore it. (Without any errors of missing method overridden of an interface)

public class PersonalAccountHolder implements BankCustomer {
 @Override
 public Customer getCustomer(String id) {
 //return customer
 }
 @Override
 public void setCustomer(String id) {
 //set customer
 }
}

Although getCustomer() and setCustomer() are must to implement. It is optional to override default method getAccountInfo() and application will not complain at the time of compilation. However, developer may decide to override this method when necessary and you can even redefine it as an abstract method in an abstract class, which in turn will force all child classes of that abstract class to implement it.

public class BusinessAccountHolder implements BankCustomer{
 @Override
 public Customer getCustomer(String id) {
 // return customer
 }
 @Override
 public void setCustomer(String id) {
 // set customer
 }
 // overriding default methods allows you to handle different logic for class
 @Override
 public String getAccountInfo(String id) {
 // return account details of customer
 }
}
public abstract class PersonalAccountHolder implements BankCustomer {
 public abstract String getAccountInfo(String id);
}

Now all classes which extends PersonalAccountHolder must need to implement getAccountInfo method. If another interface implements the interface with default methods then child interface can redefine default methods and all classes implementing child interface will use implementation of child interface instead of the one specified by the parent interface.
When multiple interfaces have default method with same signature then we will have multiple inheritance problem in implementing class. In such case class will have to provide implementation for default method or explicitly specify interface name before calling default method. Let us see the below example:

public interface BankCustomer {
 default String getAccountInfo(String id) {
 // return account info of customer
 return null;
 }
}
public interface CreditUnionCustomer {
 default String getAccountInfo(String id){
 // return account info of customer
 return null;
 }
}
public class PersonalAccountHolder implements BankCustomer,CreditUnionCustomer {
 @Override
 public String getAccountInfo(String id) {
 // implement default method here
 }
}

If we want to invoke implementation of a particular interface then we can do so as follows,

public class PersonalAccountHolder implements BankCustomer,CreditUnionCustomer {
 @Override
 public String getAccountInfo(String id) {
 return BankCustomer.super.getAccountInfo(id);
 }
}

You cannot use default methods to override any methods of Object class as Object is base class of all java classes. In case any of the classes in hierarchy of the implementing class has a method with same signature, the default method becomes irrelevant. Since all the classes in Java inherit Object, that will make all the default methods with same signature as a method from Object class irrelevant.

For example:

default int hashCode(){
}

When you do something like this it will throw compilation error like “Default method ‘hashcode’ overrides a member of ‘java.lang.Object’”.

Important points about Default methods:

  1. Default methods will help us to add new functionality to application framework without worrying about breaking implementation classes.
  2. With Default methods in an interface we can eliminate need for utility classes at some places and have all relevant code at the same place.
  3. Default methods are not mandatory to be overridden by implementing classes.
  4. Default methods cannot override any methods of Object class.
  5. Default methods in Java interface also called as “Defender Methods” or “Virtual Extension Methods”.

Static Methods

We already know this: “Static method is associated with a class and every instance of class shares same static method and we can call those methods with class name itself.”  With Java 8, Oracle introduced something similar for interfaces. Now we can declare static methods in an interface itself and call them by using interface name from all the classes which implements that interface.
Prior to Java 8, we had to create utility classes to define static methods, but now Java has the support for static methods in interface itself, which helps to keep code clean and understandable. With this approach it’s easy to organize helper methods in your application framework.
Syntax is similar to default methods we just need to use static keyword instead of default.

public interface BankCustomer {
 default String getAccountInfo(String id) {
 // return account info of customer
 return null;
 }
 static int totalBankCustomerCnts(){
 // return customer count
 }
}

In the given example, we have static method totalBankCustomerCnts defined in an interface. We can call them in implementation class as below:

public class PersonalAccountHolder implements BankCustomer,CreditUnionCustomer {
 @Override
 public String getAccountInfo(String id) {
 return BankCustomer.super.getAccountInfo(id);
 }
 // Calling static method with Interface name itself without creating an instance
 int custCount = BankCustomer.totalBankCustomerCnts();
}

When you try to call static method through an instance it will throw compilation error.
When class overrides static methods of its interface, we can add method with same signature like static method of an interface but that is not overriding actual method as static method can only by called by an Interface itself.
Similar like default method we cannot define static method for Object class method, if we do so then we will get compilation error for it.

Note: Java functional interface can have multiple default and static methods.

Important points about static methods:

  1. Static methods are part of interface and cannot be used with implementation class objects.
  2. Static methods are introduced in an interface to remove utility classes such as famous “Collections” class for example, Collections.sort() and all static methods of it moved to corresponding interface.
  3. Static method can be used effectively to create utility methods in an interface.
  4. Java functional interface can have multiple default and static methods

Abstract Class vs Java 8 Interface

After introduction of default methods the interfaces have become so similar to Abstract Classes. This feature has definitely narrowed down gap between Interface and Abstract Class. Let’s see now what differentiates Abstract Classes from Interfaces

Abstract Class  Java 8 Interface
instance variables Yes No
Constructor Yes No
Declare constants Yes Yes
Abstract methods Yes Yes
Instance Methods with implementation Yes, with default keyword Yes
Static methods Yes Yes

 

Summary

Default and static methods have definitely added more flexibility to the interfaces. We can define a default method in interface and don’t have to worry about the older implementations of that interface.  Many Java framework interface has been updated extensively by adding default and static methods to them. Some notable Interfaces are Iterator, Collection, Comparator, Iterable.

Like this post? Don’t forget to share it!