If the method declarations are identical, there is no issue - the implementing class simply needs to define this method.
When both interfaces declare methods with the same signature but different return types, it depends on the specific return types.
Method overriding in Java has been
covariant with respect to the return type since Java 5. This means that in a subclass, the return type of a method can be a subtype: the
super
method returns
Number
, the
@Override
method returns
Integer
.
If the return types are not related through inheritance, such as
String
and
Long
, the class
cannot be implemented.
For primitives, there is no covariance in return types, even if the types are
assignment compatible:
int
→
long
,
int
→
Integer
. In any such case, there will be an incompatible return types error;
primitives have to match exactly.
If the difference is in the throws
clause, with methods declared to throw different types of exceptions, the rules are the same as for return types - covariance applies. The difference is that there are no primitive exceptions, and even for exceptions that are not in a parent-child relationship, there is always an option that satisfies both - no exceptions thrown at all.
If the method is default in both interfaces, meaning it comes with a provided implementation, the compiler will immediately recognize that it will be impossible to determine which method is intended at the call site. So, the compiler will give an error "inherits unrelated defaults" at the class declaration.
In this case, the class must override the common method and explicitly direct the call to the desired parent interface’s implementation. There is syntax for explicitly specifying the base interface with
MyBase.super.doSmth()
. See the example below.
The error will occur even if the implementations are identical. If the compiler allowed this, it would be unsafe to change and recompile just one of the implementations.
In practice, this situation can arise even with classes from the standard library.
For example, if you implement both
List
and
Set
in a single class, you will encounter this error for the
spliterator()
method.
If at least one of the parent interfaces does not provide a default implementation for the method, the compilation error will suggest an alternative solution — making the class abstract. Adding the
abstract
keyword brings you back to the same ambiguity, leading to the original error.
No other differences are possible – changing other method modifiers in an interface is not allowed, and changing the parameter list or name simply makes it a different method.