Resolution Rules
Following rules are applied when overriding methods:
- Classes win over interfaces. If a class in the superclass chain has a declaration for the target method (concrete or
abstract), there's no ambiguity.
- More specific interfaces win over less specific ones. Here specificity means subtyping.
A default from List
wins
over a default (having same signature) from Collection.
If there is no unique winner according to the above rules, concrete classes must disambiguate
manually. Like we did in our example by overriding getBonus() in DefaultEmployeeEx
Multiple Inheritance of Behavior
As we saw in above example, default methods provide a way to inherit multiple implementation of methods which is
similar to multiple
inheritance. But that's limited to behavior only and not the state as we cannot add instance variable to interfaces
and we shouldn't be allowed to do that, otherwise there will be no difference between an abstract class and
interface then.
In above example, we are extending DefaultEmployee from
DomainObject class. Imagine if we don't have default methods and still want to generalize
the two methods getBonus() and getEmployeeInfo() , then possibly we would be
creating an intermediate class say AbstractEmployee extends DomainObject and putting the
two concrete methods there. Conceptually those
methods got nothing to do for being in DomainObject or it's abstract subclass. They should be isolated. Hence we have a
more generic and clear way to design our hierarchies by
adding behavior as default methods.
Also checkout this swing example,
where it shows how to add new functionality in default methods hence achieving multiple inheritance.
Why just don't use Utility methods?
One old way to achieve the same behavior is to create utility methods (getBonus(..) and getEmployeeInfo(..)), say in a class Employees and pass a specific employee instance along with other
information to those
static methods.
The disadvantage of doing that is: it's not very object oriented way. If we have multiple specialized types
of
Employee we would end up creating multiple static methods for each specialized behavior
(instead of overriding that behavior) or putting different logic path using instance of in
a
single static method. That would result in
a lot of boilerplate, not very maintainable code. Additionally util methods cannot be discovered by tools and IDEs
because they are not bound by any kind of contract on language level.
synchronized not allowed on default/static methods
Synchronization is about coordinating shared access to mutable state. It is the class that owns the state that gets
to determine that object's synchronization policy not the interfaces. This is the reason synchronized
is not deliberately allowed in Java 8 interface default methods, just like other abstract methods
default/static methods cannot be final
final default methods are not allowed. The reason is, then the body would not simply be the default implementation,
it would be the only implementation.
Also in case of ambiguity where we have to override the default method and disambiguate manually, we can't do that
if one or both methods are final. The behavior is not definable.
Only public and private Modifiers allowed on default/static methods
Since interfaces have always been restricted for having only public members, in Java 8, only public access
modifier were allowed on default/static methods.
Starting Java 9, default/static methods in interfaces can have private modifiers as well.
Default method cannot override equals/hashCode/toString methods
All interfaces implicitly override methods from object class. That is the reason we can do something like this without compile time error:
Runnable r1 = getRunnable();
Runnable r2 = getRunnable();
if(r1.equals(r2)){
......
}
r1.clone();
Since all instances of interfaces are Objects, all instances of interfaces have non-default implementations of equals/hashCode/toString already. Therefore, defining a default version of these in an interface is always useless
and will cause compile time error.
Reflection Support
A new method has been added: java.lang.Method#isDefault() (example)
|