Java Reference
In-Depth Information
Let's consider a
Sizeable
interface and a
Bag
class that implement the interface.
public interface Sizeable {
int size();
}
public class Bag implements Sizeable {
private int size;
@Override
public int size() {
return size;
}
public boolean isEmpty() {
return (size == 0);
}
// More code goes here
}
The
Bag
class overrides the
size()
method of the
Sizeable
interface. The class contains an additional concrete
method
isEmpty()
. There is no problem at this point. Now, the designer of the
Sizeable
interface decides to add a
default isEmpty() method to the interface that will look as follows:
public interface Sizeable {
int size();
// A new default method. Cannot declare it final
default boolean isEmpty() {
return (size() == 0);
}
}
After the new default
isEmpty()
method is added to the
Sizeable
interface, the
Bag
class will continue to
work. The class simply overrides the default
isEmpty()
method of the
Sizeable
interface. If it were allowed to
declare the default
isEmpty()
method
final
, it would have resulted in an error as a final method is not allowed to
be overridden. The rule not to allow a
final
default method ensures backward-compatibility. The existing classes
will continue to work if the class contains a method and a default method with the same signature is added in the
interfaces the class implements.
The Most Specific Superinterface Wins
This rule tries to resolve the inheritance of a complicating method with the same signature from multiple interfaces.
If the same method (abstract or default) is inherited from multiple superinterfaces through different paths, the most
specific path is used. Suppose
I1
is an interface with a method
m(). I2
is a subinterface of
I1
and
I2
overrides the
method
m()
. If a class
Test
implements both interfaces
I1
and
I2
, it has two choices of inheriting the
m()
method