Java 8 onward Default and Static Methods Example

Introduction

In this tutorial I am going to show how default and static methods can be included into Java 8 interfaces.

Prior to Java 8 you did not have such mechanism to include default method or static method into interface but Java 8 provides such option to include those methods.

Prior to Java 8 if a new methods was added to the interface then all implementing classes used to break and implementation for the new method must have been provided in all classes that implemented the interface.

Java 8 or later version onward you can add default and static methods in interfaces.

Static methods are regarded as utility methods, not as essential, core methods. Whereas default methods are treated as common behaviors for all the client classes.

Prerequisites

Java at least version 8

Default Methods

Default methods were introduced to provide backward compatibilities for old interfaces so that they can have new methods without breaking the existing code.

Therefore sometimes methods have single implementation and there is no need to provide their implementations in each class. In that case you can declare the method as a default method with its implementation in the interface itself.

A default keyword is specified at the begining of the method signature to create a default method in an interface. So default methods can have a body.

When you extend an interface that contains a default method, you would get the following benefits:

  • If you do not mention the default method at all, which lets your extended interface inherit the default method.
  • If you re-declare the default method, which makes it abstract.
  • If you redefine the default method, which overrides it.

Example of default methods in Java interface can be written as given below:

public interface InterfaceDefaultMethods {

	LocalDateTime getLocalDateTime();

	default ZonedDateTime getZonedDateTime(String zoneString) {
		return ZonedDateTime.of(getLocalDateTime(), ZoneId.of(zoneString));
	}

	default String getHello() {
		return "Hello";
	}

}

Static Methods

Static methods are defined in interfaces with static keyword. Static methods cannot be overridden in implementation classes.

Static methods in Java interfaces are visible to interface methods only.

Like other static methods interface methods can be accessed using interface name.

Java interface static methods are good for providing utility methods, for example, null check, sorting collections, etc.

Static methods in interface provide security by not allowing overridden in implementation classes.

Examples of static methods in Java interface can be written as given below:

public interface InterfaceStaticMethods {

	static ZoneId getZoneId(String zoneString) {
		try {
			return ZoneId.of(zoneString);
		} catch (DateTimeException e) {
			System.err.println("Invalid time zone: " + zoneString + "; using default time zone instead.");
			return ZoneId.systemDefault();
		}
	}

	static String getMsg() {
		return "Hello, World!";
	}

}

Even you can write both default and static methods in Java interfaces as shown below:

public interface InterfaceDefaultStaticMethods {

	LocalDateTime getLocalDateTime();

	static ZoneId getZoneId(String zoneString) {
		try {
			return ZoneId.of(zoneString);
		} catch (DateTimeException e) {
			System.err.println("Invalid time zone: " + zoneString + "; using default time zone instead.");
			return ZoneId.systemDefault();
		}
	}

	static String getMsg() {
		return "Hello, World!";
	}

	default ZonedDateTime getZonedDateTime(String zoneString) {
		return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
	}

	default String getHello() {
		return "Hello";
	}

}

Example

Now I am going to create the example with both default and static methods in interface with a class implementation.

Interface with default and static methods

The following interface contains both static and default methos:

public interface InterfaceDefaultStaticMethods {

	LocalDateTime getLocalDateTime();

	static ZoneId getZoneId(String zoneString) {
		try {
			return ZoneId.of(zoneString);
		} catch (DateTimeException e) {
			System.err.println("Invalid time zone: " + zoneString + "; using default time zone instead.");
			return ZoneId.systemDefault();
		}
	}

	static String getMsg() {
		return "Hello, World!";
	}

	default ZonedDateTime getZonedDateTime(String zoneString) {
		return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
	}

	default String getHello() {
		return "Hello";
	}

}

Implementation Class

The implementation class that basically implements the above interface. This class only has to override the abstract method which is written in the above interface. The default methods will be inherited in the implementation class.

public class ClassDefaultStaticMethods implements InterfaceDefaultStaticMethods {

	@Override
	public LocalDateTime getLocalDateTime() {
		return LocalDateTime.now();
	}

}

Usage

Now I will create a class with main method to test default and static methods in the Java interface.

public class DefaultStaticMethodsExample {

	public static void main(String[] args) {
		InterfaceDefaultStaticMethods defaultStaticMethods = new ClassDefaultStaticMethods();
		System.out.println("Current Time: " + defaultStaticMethods.getLocalDateTime());
		System.out.println("Zonal Time: " + defaultStaticMethods.getZonedDateTime("US/Eastern"));
		System.out.println("getHello: " + defaultStaticMethods.getHello());
		System.out.println("getZoneId: " + InterfaceDefaultStaticMethods.getZoneId("US/Central"));
		System.out.println("getMsg: " + InterfaceDefaultStaticMethods.getMsg());
	}

}

Output

The output from the above main class will be as follows:

Current Time: 2021-08-16T11:36:25.124479500
Zonal Time: 2021-08-16T11:36:25.125479400-04:00[US/Eastern]
getHello: Hello
getZoneId: US/Central
getMsg: Hello, World!

Diamond Problem

Let’s consider you have two interfaces with same signature of default methods then you will face a diamond problem and your implement class must override the default method.

Interface1

public interface Interface1 {

	default String getMsg() {
		return "Hi";
	}

}

Interface2

public interface Interface2 {

	default String getMsg() {
		return "Hello";
	}

}

Implementation Class

public class ClassInterface implements Interface1, Interface2 {

}

Now you will see that Java compiler complains to override the default methods:

default and static methods in java interface

Now overriding any one of the interfaces methods will fix the compilation error. Either you can return the same implementation from the interface default method or you can implement your own logic in the overridden method in the implementation class. For example,

public class ClassInterface implements Interface1, Interface2 {

	@Override
	public String getMsg() {
		//return Interface1.super.getMsg(); //from the interface
		return "Greeting"; //own implementation
	}

}

But you won’t face any such diamond problem for static methods in interfaces because you have to access static methods using the interface name in the same way you access static methods from the class using the class name.

Source Code

Download

Leave a Reply

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