Whenever we have a choice between abstract class and interface we should always (almost) prefer default (also known as defender or virtual extensions) methods.
Default methods have put an end to classic pattern of interface and a companion class that implements most or all of the methods in that interface. An example is Collection and AbstractCollection
. Now we should implement the methods in the interface itself to provide default functionality. The classes which implement the interface has choice to override the methods or inherit the default implementation.
Another important use of default methods is interface evolution
. Suppose I had a class Ball as:
public class Ball implements Collection { ... }
Now in Java 8 a new feature streams in introduced. We can get a stream by using stream
method added to the interface. If stream
were not a default method all the implementations for Collection
interface would have broken as they would not be implementing this new method. Adding a non-default method to an interface is not source-compatible
.
But suppose we do not recompile the class and use an old jar file which contains this class Ball
. The class will load fine without this missing method, instances can be created and it seems everything is working fine. BUT if program invokes stream
method on instance of Ball
we will get AbstractMethodError
. So making method default solved both the problems.
Java 9 has got even private methods in interface which can be used to encapsulate the common code logic that was used in the interface methods that provided a default implementation.