What is default method in interface?

What is default method in interface?

Introduction

Java 8 introduced many new features, for example static and default method in interface along with lambda expressions, Functional Interfaces, Stream etc. Default methods (also known as defender methods or virtual extension methods) assist developers in adding new methods with a default implementation to the interface without worrying about breaking any existing implementation. This way developers have flexibility to not implement the default methods in their implementation because these methods will already have already been defied by default.

In this article, we’ll discuss in depth about how to use default methods in interfaces. We’ll also try to understand the applicable use cases and challenges using default methods in interfaces.

Let’s understand this with a quick example –

/* An example for default interface method */
public interface MyInterface {
	// A regular method in interface 
	public void print();
	
	// Newly defined default method in interface
	default void print(String str) {
		System.out.println("Printing on MyInterface: " + str);
	}	
}

// Concrete class
public class MyClass implements MyInterface{
	@Override
	public void print() {
		// Regular Interface method - needs implementation
		System.out.println("Implemented method.");
	}
}

In the above code, we have interface MyInterface which already had an existing method print(), and now a new method print(String) is being added as default method. Note that our implementation class MyClass doesnt have to implement default method print(String) if it doesnt want to.

What is the need for Default Method

Lets start with an example for JDK collections example in Java 8 where a new forEach method is added to work with Lambdas.

public interface Iterable {
		public void forEach(Consumer consumer);
}


If a new method is added to interface in this way, it will break all the classes implementing the Iterator and there will be a lot of compilation errors. To solve this problem a default method with some default implementation should be added so that the existing implementation doesn’t need to be changed. So, the Iterable interface with the could be rewritten as below with the help of a default method to avoid breaking the implementation:

	public interface Iterable {
	public default void forEach(Consumer consumer) {
			for (T t : this) {
				consumer.accept(t);
			}
		}
	}

Note – a similar mechanism is used to add Stream in Java 8 – without breaking anything in JDK.

If each newly added method in an interface with an implementation as well, then there won’t be any impact on implementing classes.

Abstract class vs Default Method Interface – Java 8

With Default Method in Java 8, it might appear that since Interfaces can have implementation in them they are same as Abstract classes. However this is not true because merely having concrete methods (with implementation) in interfaces doesn’t make the interfaces similar to abstract class. There are still many differences, for example –

Abstract ClassDefault method Interface
Constructors The abstract class can define constructors.No constructors for Interfaces
Structure and stateThey are more structured and can have a state associated with them.Default method can be implemented only in the terms of invoking other interface methods, State doesn’t matter.
PurposePurpose of abstract class is to provide partial abstraction.The purpose of interface is to provide full abstraction. The interface is like a blueprint for your class, with the introduction of default methods you can simply say that we can add additional features in the interfaces without affecting the end user classes
Comparison of Abstract class vs default method in interfaces – Java 8

Hence, choice between interface and abstract class depends on the use case and the context since both are still used for different context.

Multiple Inheritance with Default Method

Default methods in interface are a good features, but there’s one thing where you have to be careful – multiple interfaces, it’s important to know what happens when a class implements several interfaces that define the same default methods.

Multiple Inheritance with Default Method in interface
Multiple Inheritance with Default Method in interface – ambiguity? How to resolve this?

Take an example from the above, Interface1 & Interface2 both define a default method each with the name of defaultMethod(), which is a conflict for implementing class. So, for any class implementing multiple interfaces there could be conflict if their are more than one default methods with the same name.

Lets understand with the help of an example –

// Interface1.java
public interface Interface1 {
	public default void defaultMethod() {
		System.out.println("Inside Interface1");
	}
}
// Interface2.java
public interface Interface2 {
	public default void defaultMethod() {
		System.out.println("Inside Interface2");
	}
}
// MyClass.java
public class MyClass implements Interface1, Interface2{

}

The code above will fail to compile due to below error caused by conflict of multiple interface inheritance. This is also known as Diamond problem in Java.

Compilation error due to conflict of common name of default method in interface
Compilation error due to conflict of common name of default method in interface

So, how do we solve this error. Simple, override the method in your class as below.

public class MyClass implements Interface1, Interface2{
	@Override
	public void defaultMethod() {
		/*
		 * 1. Interface1.super.defaultMethod();
		 * 2. Interface2.super.defaultMethod();
		 * 3. Or any other implementation
		 */
	}
}

As shown above, its simple to fix the error by having an overridden method which can either 1). call Interface1’s default method or, 2). call Interface2’s default method or have your own implementation.

Default Method vs Regular Method

Like regular interface methods, default methods are implicitly public — there’s no need to specify the public modifier.

• Default Method is defined with a default keyword at the beginning of the method signature and that’s the first difference with regular method.
• Default Method can only access arguments passed to it as interfaces don’t have field or state added to them, while regular methods in classes can use and modify method arguments as well as the fields of their class.

What to do with default methods

As discussed, the default methods were introduced to provide backward compatibility so that existing interfaces can use the lambda expressions without actually implementing them in the concrete classes. In general, default methods provide ability to add new functionality to existing interfaces without breaking older implementation of these interfaces.

We can do following things in the concrete classes implementing interfaces with default methods –

  • Do not override the default method, instead just inherit the default implementation of the method.
  • Similar to other ‘regular’ methods from the interface, you can override the default method as well.
  • You can define default method as abstract and force subclass to override it.

By having a default interface methods we can –

  • Preserve backward compatibility by giving ability to incrementally provide additional functionality in existing interface without breaking down the implementing classes.
  • Help developers in achieving additional functionality around an existing abstract method:

Remember Java 8 brought a lot of changes with respect to Lambda, Stream, forEach etc – which might have impacted the implementing classes because of new methods being added to interfaces. Re-engineering an existing JDK framework is always very complex. Modifying one interface in a JDK framework breaks all classes meaning millions of lines of code possibly and causing havoc. Therefore, default methods have assisted with mechanism to extend interfaces in a backward-compatible way.

Default Method vs Static Method in interface

Just like static method of the classes, the interfaces can also have static methods. These are similar to the default methods in interfaces introduced in Java 8, except that we cannot override these methods in the classes that implements these interfaces.

  • Static interfaces methods don’t belong to a particular object, they are not part of the API of the classes implementing the interface. Their name is – interface name preceding the method name.
  • No need to implement them in the implementation classes just like default methods. Since these methods are static, we cannot override them in the implementation classes.
  • A static interfaces method can be invoked within other static and default interfaces methods.
  • The idea is that these methods can provide a simple mechanism to allow us to increase the degree of cohesion of a design. This is achieved by putting together related methods in one single place without having to create an object.
  • Also, these methods make possible to group related utility methods, without having to create artificial utility classes that are simply placeholders for static methods.

Lets see how does static method work –

// StaticMethodInterface.java
public interface StaticMethodInterface {

	// Existing method in interface
	public void regularMethod();

	// new static method added
	static void doSomething() {
		System.out.println("Inside Static method.");
	}
}

// StaticMethodClass.java
public class StaticMethodClass implements StaticMethodInterface {

	@Override
	public void regularMethod() {
		/*
		 * Only existing method overridden, not the static method
		 */
		System.out.println("Routine method implemented.");
	}

}

// StaticMethodSample.java
public class StaticMethodSample {

	public static void main(String[] args) {
		StaticMethodInterface sm = new StaticMethodClass();
		sm.regularMethod();
		// Static method called using interface
		StaticMethodInterface.doSomething();
	}
}

Important Points

  1. After Java 8 now interfaces can have a default method implementation in them as well.
  2. Interfaces can have static methods as well, similar to static methods in classes.
  3. Default methods or defender methods in interfaces are to allow the developers to add new methods to the interfaces. This way there will not be anything affecting the classes that implements these interfaces.
  4. Default methods were introduced to provide backward compatibility for old interfaces. Reason being – that they can have new methods without affecting existing code.
  5. Remember, earlier the interfaces in Java could only have abstract methods without implementation.

Conclusion

In this article, we explored in depth the use of static and default methods in interface in Java 8. This new feature in Java to have default methods in interfaces may look a little unconventional. Especially when we know from object oriented perspective that interfaces are not expected to have behavior implemented. Also, they should be used to define the public contract only. However, to support backward compatibility with existing code this is definitely a big support.

And, as usual, all the code samples shown in this article are available over CodingCampus repository in GitHub.

Further Reading

Was this page helpful? Please use the commenting form below to ask any questions or to make a comment. Please do not put the same comment multiple times. Your comment will appear after some time. Also please note that we do not reply to emails or comments on social media. So if you have any question, please put it in the form below, we will try to reply to it as soon as possible. If you are facing any issue with the code provided in the blog, please be as specific with your requirements. We usually reply within a day. 

Follow my blog with Bloglovin

Leave a Reply

Your email address will not be published. Required fields are marked *