Member-only story
Effective Java! Design Interfaces for Posterity
Today we are focusing again on interfaces. The focus of today’s chapter was largely on a feature that was added in Java 8, default methods. The problem that default methods try to solve is, before Java 8, once an interface was released to the wild you could never change it safely. If you did, the classes that implemented it would encounter an error as they would no longer be implementing the full interface. So how do default methods attempt to solve this problem? What they allow us to do is provide a default implementation for a particular method so we can evolve an interface without requiring the consumer of the service to implement that method right away.
This sounds like a great idea and it can be a great tool but what should we be aware of when using a default method? The main concern is that we don’t have a guarantee that our default implementation will work with all the implementations of the interface. An example of how this can bite us is with the removeIf
default method added to the Collection
interface in Java 8. This method takes in a Predicate
and it iterates through the collection and calls remove on all the entries that match the predicate. This seems like a simple, logical implementation and it does indeed work a lot of the time. However, for example, in the Apache Commons library there is a SynchronizedCollection
which implements the Collection
interface and basically forwards all requests onto a backing collection after locking on the object. This method does not override the removeIf
function and thus inherits…