With the introduction of default methods in Java 8, it is now possible for a class to inherit the same method from multiple places (such as another class or interface). The following rules can be used to determine which method is selected in such cases:
- A class or superclass method declaration always takes priority over a default method
- Otherwise, the method with the most specific default-providing interface is used
- Finally, if the methods are equally specific, there will be a compiler error and you will be forced to explicitly override the method and specify which one your class should call
Let's look at a few examples and apply these rules.
Example 1:
What does the following code print?
public interface A { default void name() { System.out.println("A"); } } public interface B { default void name() { System.out.println("B"); } } public class C implements A { @Override public void name() { System.out.println("C"); } } public class D extends C implements A, B { public static void main(final String... args) { new D().name(); } }
Answer: C
This is because, as stated in Rule 1, the method declaration of name()
from the superclass C
takes priority over the default methods declarations in A
and B
.
Example 2:
What does the following code print?
public interface A { default void name() { System.out.println("A"); } } public interface B extends A { @Override default void name() { System.out.println("B"); } } public class C implements A {} public class D extends C implements A, B { public static void main(final String... args) { new D().name(); } }
Answer: B
Unlike the previous example, C
does not override name()
, but since it implements A
, it has a default method from A
. According to Rule 2, if there are no methods in the class or superclass, the most specific default-providing interface is selected. Since B
extends A
, it is more specific and, as a result, "B" is printed.
Example 3:
What does the following code print?
public interface A { default void name() { System.out.println("A"); } } public interface B { default void name() { System.out.println("B"); } } public class D implements A, B { public static void main(final String... args) { new D().name(); } }
Answer: Compiler error! Duplicate default methods named name with the parameters () and () are inherited from the types B and A
In this example, there's no more-specific default-providing interface to select, so the compiler throws an error. To resolve the error, you need to explicitly override the method in D
and specify which method declaration you want D
to use. For example, if you want to use B
's:
class D implements A, B { @Override public void name() { B.super.name(); } }
Example 4:
What does the following code print?
public interface A { default void name() { System.out.println("A"); } } public interface B extends A {} public interface C extends A {} public class D implements B, C { public static void main(final String... args) { new D().name(); } }
Answer: A
The sub-interfaces B
and C
haven't overridden the method, so there is actually only the method from A
to choose from. As a side note, if either B
or C
(but not both) had overridden the method, then Rule 2 would have applied. By the way, this is the diamond problem.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.