When resolving a virtual method such as print(), the JVM searches the superclass chain for implementations as well as the transitive closure of the interfaces for default implementations. If an implementation is found in an ancestor class, it will always take precedence over a default implementation in an interface.
The reason for this rule is for compatibility.
Let's start off with a slightly modified example:
interface G { } class M { void print() { ... } } class GImpl extends M implements G { } ... new GImpl().print();
Clearly, M's print method will be called.
Now consider that G is evolved by adding a default implementation of print:
interface G { default void print() { ... } }
Recall that the primary purpose of default methods is to facilitate interface evolution. Part of this is the ability to add new methods to an interface. Another part of this is not breaking existing code. If the addition of a default method to G were to change the behavior of existing classes such as GImpl, this would most likely cause programs to break. In addition I think that most people would be surprised by this.
Thus, the rule was established that implementations in the superclass chain always take precedence over default implementations in the interfaces, so that programs won't change behavior unexpectedly if a default method is added to an interface.