I understand that in Java static methods are inherited just like instance methods, with the difference that when they are redeclared, the parent implementations are hidden rather than overridden. Fine, this makes sense. However, the Java tutorial notes that
Static methods in interfaces are never inherited.
Why? What's the difference between regular and interface static methods?
Let me clarify what I mean when I say static methods can be inherited:
class Animal {
public static void identify() {
System.out.println("This is an animal");
}
}
class Cat extends Animal {}
public static void main(String[] args) {
Animal.identify();
Cat.identify(); // This compiles, even though it is not redefined in Cat.
}
However,
interface Animal {
public static void identify() {
System.out.println("This is an animal");
}
}
class Cat implements Animal {}
public static void main(String[] args) {
Animal.identify();
Cat.identify(); // This does not compile, because interface static methods do not inherit. (Why?)
}
Before Java 8, you couldn't define
static
methods in aninterface
. This is heavily discussed in this question. I'm going to refer to this answer (by user @JamesA.Rosen) as to why the Java designers probably didn't wantstatic
methods in aninterface
initially:However, since the release of Java 8, you can actually add
default
andstatic
methods inside aninterface
.I'm going to be quoting this source a lot here. This is the initial problem:
This was the solution Java 8 provided
default
:And for
static
:Example:
Static methods in interfaces could create a diamond of death if they were being inherited. So, calling a static method from the appropriate interface is good enough compared to the risk of calling it from a concrete class that may implement multiple interfaces that contain static methods of the same name.
Why are static methods any different?
Static methods are just functions unrelated to the objects. Instead of placing them in utility abstract classes (like calling Collections.sort() ) we move those functions (static methods) to their appropriate interfaces. They could be bound to the inherited objects like the default methods do, but that is not their job. Static methods provide functionality which is unrelated to the instances of the class.
Example:
So, the point is that a Duck may float but the function that checks if an Object really floats is not something that a Duck can do. It is an irrelevant functionallity that we could pass to our Floatable interface instead of having it sit inside some utility class.
Let's begin with some background ...
Java doesn't support multiple inheritance (the ability to extend more than one class). This is because multiple inheritance is prone to the deadly diamond of death (also known as the diamond problem) which the designers of Java chose to preempt.
If B and C override a method inherited from A, which method does D inherit?
A class can implement multiple interfaces because interface methods are contracted for overriding; if a class C implements two interfaces A and B that declare the same method, then the same method in C will be invoked by clients of either interface (A or B). The introduction of default methods for interfaces in Java 8 was made possible by forcing the implementer to override the default in case of ambiguity. This was an acceptable compromise since default methods are intended to be defensive (to be used if no other implementation is explicitly provided by an implementer). However, since the compiler can’t force you to override a static method (static methods inherently can't be overridden), the introduction of static methods for interfaces in Java came with one restriction: the static methods of an interface are not inherited.
Here's my guess.
Since
Cat
can only extend one class ifCat
extendsAnimal
thenCat.identify
has only one meaning.Cat
can implement multiple interfaces each of which can have a static implementation. Therefore, the compiler would not know which one to choose?However, as pointed out by the author,
If I was to guess again, I'd say that with
default
the implementation is part ofCat
's vtable. Withstatic
it cannot be. The main function must bind to something. At compile timeCat.identify
could be replaced withAnimal.identify
by the compiler but the code wouldn't match reality ifCat
was recompiled but not the class that contains main.