The page Why are lambda expressions being added to Java? uses as an example the simple collections method forEach
, which takes a function and applies it to every element, for example:
pointList.forEach(p -> p.move(p.y, p.x));
But the classes of the Java Collections Framework, having been designed fifteen years ago for a language without a functional orientation, do not have a method forEach
, or any of the other methods that this strategy will require. Adding these methods to the Collections Framework classes individually would destroy the coherence of the highly interface-based Framework—for collections classes, it is the interface that defines the contract of that client code can depend on (for the same reason, adding static methods to the utility class Collections
is not a solution either). So the interfaces of the Framework need to reflect the new functionality that is being added to its collections. But until now adding new methods to an interface has been impossible without forcing modification to existing classes, since the implements
clause represents a commitment by the implementing class to override all abstract methods in the interface. If the interface gains a new abstract method, the implementing class must be changed to override that too.
This is the rationale for the introduction of default methods (formerly called virtual extension methods or defender methods). Their purpose is to enable interfaces to evolve without introducing incompatibility with existing implementations. The need for them has driven a significant change in the purpose of interfaces, which previously could declare only abstract methods whose semantics were defined by the contract in the JavaDoc; now, by contrast, they can also declare concrete methods in the form of default implementations. For example, Iterator
could hypothetically be extended by a method that skips a single element:
interface Iterator {
// existing method declarations
default void skip() {
if (hasNext()) next();
}
}
Suppose Iterator
were extended in this way: all implementing classes now automatically expose a skip
method, which client code can call exactly as with abstract interface methods. If skip
is called on an instance of a class that implements Iterator
without providing a body for it, then the default implementation in the interface declaration is invoked. Alternatively, since default methods are virtual, a class implementing Iterator
can override the default method with a better or more implementation-specific one.
The page Why do default methods need a keyword? answers a common question about the syntax of default methods.
Leave a Reply