Java 8 permits static interface methods
With Java 8, interfaces can have static methods. They can also have concrete instance methods, but not instance fields.
There are really two questions here:
- Why, in the bad old days, couldn't interfaces contain static methods?
- Why can't static methods be overridden?
Static methods in interfaces
There was no strong technical reason why interfaces couldn't have had static methods in previous versions. This is summed up nicely by the poster of a duplicate question. Static interface methods were initially considered as a small language change, and then there was an official proposal to add them in Java 7, but it was later dropped due to unforeseen complications.
Finally, Java 8 introduced static interface methods, as well as override-able instance methods with a default implementation. They still can't have instance fields though. These features are part of the lambda expression support, and you can read more about them in Part H of JSR 335.
Overriding static methods
The answer to the second question is a little more complicated.
Static methods are resolvable at compile time. Dynamic dispatch makes sense for instance methods, where the compiler can't determine the concrete type of the object, and, thus, can't resolve the method to invoke. But invoking a static method requires a class, and since that class is known statically—at compile time—dynamic dispatch is unnecessary.
A little background on how instance methods work is necessary to understand what's going on here. I'm sure the actual implementation is quite different, but let me explain my notion of method dispatch, which models observed behavior accurately.
Pretend that each class has a hash table that maps method signatures [name and parameter types]
to an actual chunk of code to implement the method. When the virtual machine attempts to invoke a method on an instance, it queries the object for its class and looks up the requested signature in the class's table. If a method body is found, it is invoked. Otherwise, the parent class of the class is obtained, and the lookup is repeated there. This proceeds until the method is found, or there are no more parent classes—which results in a NoSuchMethodError
.
If a superclass and a subclass both have an entry in their tables for the same method signature, the sub class's version is encountered first, and the superclass's version is never used—this is an "override".
Now, suppose we skip the object instance and just start with a subclass. The resolution could proceed as above, giving you a sort of "overridable" static method. The resolution can all happen at compile-time, however, since the compiler is starting from a known class, rather than waiting until runtime to query an object of an unspecified type for its class. There is no point in "overriding" a static method since one can always specify the class that contains the desired version.
Constructor "interfaces"
Here's a little more material to address the recent edit to the question.
It sounds like you want to effectively mandate a constructor-like method for each implementation of IXMLizable
. Forget about trying to enforce this with an interface for a minute, and pretend that you have some classes
that meet this requirement. How would you use it?
class Foo implements IXMLizable {
public static Foo newInstanceFromXML[Element e] { ... }
}
Foo obj = Foo.newInstanceFromXML[e];
Since you have to explicitly name the concrete type Foo
when "constructing" the new object, the compiler can verify that it does indeed have the necessary factory method. And if it doesn't, so what? If I can implement an IXMLizable
that lacks the "constructor", and I create an instance and pass it to your code, it is an IXMLizable
with all the necessary interface.
Construction is part of the implementation, not the interface. Any code that works successfully with the interface doesn't care about the constructor. Any code that cares about the constructor needs to know the concrete type anyway, and the interface can be ignored.
Prior to java 8, interface in java can only have abstract methods. All the methods of interfaces are public & abstract by default. Java 8 allows the interfaces to have default and static methods. The reason we have default methods in interfaces is to allow the developers to add new methods to the interfaces without affecting the classes that implements these interfaces.
For example, if several classes such as A
, B
, C
and D
implements an interface XYZInterface
then if we add a new method to the XYZInterface
, we have to change the code in all the classes[A, B, C and D] that implements this interface. In this example we have only four classes that implements the interface which we want to change but imagine if there are hundreds of classes implementing an interface then it would be almost
impossible to change the code in all those classes. This is why in java 8, we have a new concept “default methods”. These methods can be added to any existing interface and we do not need to implement these methods in the implementation classes mandatorily, thus we can add these default methods to existing interfaces without breaking the code.
We can say that concept of default method is introduced in java 8 to add the new methods in the existing interfaces in such a way so that they are backward compatible. Backward compatibility is adding new features without breaking the old code.
Static methods in interfaces are similar to the default methods except that we cannot override these methods in the classes that implements these interfaces.
Java 8 Example: Default method in Interface
The method newMethod[]
in MyInterface
is a default method, which means we need not to implement this method in the implementation class
Example
. This way we can add the default methods to existing interfaces without bothering about the classes that implements these interfaces.
interface MyInterface{ /* This is a default method so we need not * to implement this method in the implementation * classes */ default void newMethod[]{ System.out.println["Newly added default method"]; } /* Already existing public and abstract method * We must need to implement this method in * implementation classes. */ void existingMethod[String str]; } public class Example implements MyInterface{ // implementing abstract method public void existingMethod[String str]{ System.out.println["String is: "+str]; } public static void main[String[] args] { Example obj = new Example[]; //calling the default method of interface obj.newMethod[]; //calling the abstract method of interface obj.existingMethod["Java 8 is easy to learn"]; } }
Output:
Newly added default method String is: Java 8 is easy to learn
Java 8 Example: Static method in Interface
As mentioned above, the static methods in interface are similar to default method so we need not to implement them in the implementation classes. We can safely add them to the existing interfaces without changing the code in the implementation classes. Since these methods are static, we cannot override them in the implementation classes.
interface MyInterface{ /* This is a default method so we need not * to implement this method in the implementation * classes */ default void newMethod[]{ System.out.println["Newly added default method"]; } /* This is a static method. Static method in interface is * similar to default method except that we cannot override * them in the implementation classes. * Similar to default methods, we need to implement these methods * in implementation classes so we can safely add them to the * existing interfaces. */ static void anotherNewMethod[]{ System.out.println["Newly added static method"]; } /* Already existing public and abstract method * We must need to implement this method in * implementation classes. */ void existingMethod[String str]; } public class Example implements MyInterface{ // implementing abstract method public void existingMethod[String str]{ System.out.println["String is: "+str]; } public static void main[String[] args] { Example obj = new Example[]; //calling the default method of interface obj.newMethod[]; //calling the static method of interface MyInterface.anotherNewMethod[]; //calling the abstract method of interface obj.existingMethod["Java 8 is easy to learn"]; } }
Output:
Newly added default method Newly added static method String is: Java 8 is easy to learn
Java 8 – Abstract classes vs interfaces
With the introduction of default methods in interfaces, it seems that the abstract classes are same as interface in java 8. However this is not entirely true, even though we can now have concrete methods[methods with body] in interfaces just like abstract class, this doesn’t mean that they are same. There are still few differences between them, one of them is that abstract class can have constructor while in interfaces we can’t have constructors.
The purpose of interface is to provide full abstraction, while the purpose of abstract class is to provide partial abstraction. This still holds true. The interface is like a blueprint for your class, with the introduction of default methods you can simply say that we can add additional features in the interfaces without affecting the end user classes.
Default Method and Multiple Inheritance
The multiple inheritance problem can occur, when we have two interfaces with the default methods of same signature. Lets take an example.
interface MyInterface{ default void newMethod[]{ System.out.println["Newly added default method"]; } void existingMethod[String str]; } interface MyInterface2{ default void newMethod[]{ System.out.println["Newly added default method"]; } void disp[String str]; } public class Example implements MyInterface, MyInterface2{ // implementing abstract methods public void existingMethod[String str]{ System.out.println["String is: "+str]; } public void disp[String str]{ System.out.println["String is: "+str]; } public static void main[String[] args] { Example obj = new Example[]; //calling the default method of interface obj.newMethod[]; } }
Output:
Error: Duplicate default methods named newMethod with the parameters [] and [] are inherited from the types MyInterface2 and MyInterface
This is because we have the same method in both the interface and the compiler is not sure which method to be invoked.
How to solve this issue?
To solve this problem, we can implement this method in the implementation class like this:
interface MyInterface{ default void newMethod[]{ System.out.println["Newly added default method"]; } void existingMethod[String str]; } interface MyInterface2{ default void newMethod[]{ System.out.println["Newly added default method"]; } void disp[String str]; } public class Example implements MyInterface, MyInterface2{ // implementing abstract methods public void existingMethod[String str]{ System.out.println["String is: "+str]; } public void disp[String str]{ System.out.println["String is: "+str]; } //Implementation of duplicate default method public void newMethod[]{ System.out.println["Implementation of default method"]; } public static void main[String[] args] { Example obj = new Example[]; //calling the default method of interface obj.newMethod[]; } }
Output:
Implementation of default method