This means that when defining an abstract type (e.g., Shape ) that you expect to have
many subtypes (e.g., Circle , Rectangle , Square ), you are faced with a choice
between interfaces and abstract classes. Because they now have very similar features,
it is not always clear which to use.
Remember that a class that extends an abstract class cannot extend any other class,
and that interfaces still cannot contain any nonconstant fields. This means that
there are still some restrictions on how we can use object orientation in our Java
Another important difference between interfaces and abstract classes has to do with
compatibility. If you define an interface as part of a public API and then later add a
new mandatory method to the interface, you break any classes that implemented the
previous version of the interface—in other words, any new interface methods must
be declared as default and an implementation provided. If you use an abstract class,
however, you can safely add nonabstract methods to that class without requiring
modifications to existing classes that extend the abstract class.
In both cases, adding new methods can cause a clash with
subclass methods of the same name and signature—with the
subclass methods always winning. For this reason, think care‐
fully when adding new methods—especially when the method
names are “obvious” for this type, or where the method could
have several possible meanings.
In general, the suggested approach is to prefer interfaces when an API specification
is needed. The mandatory methods of the interface are nondefault, as they represent
the part of the API that must be present for an implementation to be considered
valid. Default methods should be used only if a method is truly optional, or if they
are really only intended to have a single possible implementation. This latter exam‐
ple is the case for the functional composition present in java.util.function.Func
tion —functions will only ever be composed in the standard way, and it is highly
implausible that any sane override of the default compose() method could exist.
Finally, the older technique of merely documenting which methods of an interface
are considered “optional” and just throwing a java.lang.UnsupportedOperationEx
ception if the programmer does not want to implement them is fraught with prob‐
lems, and should not be used in new code.
Instance Methods or Class Methods?
Instance methods are one of the key features of object-oriented programming. That
doesn't mean, however, that you should shun class methods. In many cases, it is per‐
fectly reasonable to define class methods.