Default interface functions in Java 8
November 7, 2014 Leave a comment
Introduction
A new feature in Java 8 is default function implementations. They are default implementations of methods of an interface. Default methods can help extending an interface without breaking the existing implementations. After all if you add a new method to an interface then all implementing types must handle it otherwise the compiler will complain.
This can be cumbersome if your interface has a large number of consumers. You’ll break their code and they will need to implement the new function – which they might not even need.
The default keyword for interfaces
In .NET the above problem can be easily solved by extension methods. There’s no equivalent of extension methods in Java – at least not that I know of – but it’s possible to approximate them using the ‘default’ keyword within an interface. Let’s say I have the following interface:
public interface ISomeInterface { void doSomething(); int countSomething(); void shadyFunction(); }
Then an implementing class must include all of these otherwise you get a compiler error:
public class SomeImplementor implements ISomeInterface { @Override public void doSomething() { System.out.println("Hello world"); } @Override public int countSomething() { return 1000; } @Override public void shadyFunction() { System.out.println("Let's relocate to Mars"); } }
This is extremely basic, right? Now, what if you want to extend ISomeInterface without breaking SomeImplementor? Up until Java 7 this wan’t an option, but in Java 8 it’s possible as follows:
public interface ISomeInterface { void doSomething(); int countSomething(); void shadyFunction(); default void incredibleFunction(String message) { System.out.println(message); } }
The compiler won’t complain that there’s no “incredibleFunction” implementation in SomeImplementor. You can still override it of course but you’re free to call the function from an instance of SomeImplementor:
SomeImplementor si = new SomeImplementor(); si.incredibleFunction("Fantastic!");
So the ‘default’ keyword in interfaces lets you provide a default implementation of a method without forcing the implementing classes to provide their own implementation. This is quite useful: you can extend an interface without worrying about the existing implementations.
We can see examples of default implementations throughout the new java.util.function interfaces. Predicate of T, i.e. a function that returns boolean and accepts one input parameter has an “and” default method which allows you to chain boolean operations that must be evaluated together:
Predicate<String> stringConditionOne = s -> s.length() > 20; Predicate<String> stringConditionTwo = s -> s.contains("search"); Predicate<String> combinedPredicate = stringConditionOne.and(stringConditionTwo);
The default “and” implementation of the Predicate interface will simply test both conditions and return true if both evaluate to true.
The Predicate interface also has a default static “isEqual” method whose implementation simply calls the equals method of Object if the input parameter is not null:
Predicate<String> equal = Predicate.isEqual("hello"); boolean test = equal.test("hello");
Here “test” will be true.
View all posts related to Java here.