In previous article, we have seen and learnt that defining constructor inside interface is not allowed and compiler throws error stating below reason
Interface in Java :
Compile-time error: “Interfaces cannot have constructors”
Constructor are needed to construct a new object to hold the state of an object and invoke member methods, but in Interface
- There are only static variables
- By default all variables are public, static and final (i.e.; constants)
- Methods with no concrete implementation (i.e.; all are abstract methods)
Which makes it clear that, we don’t need constructor to construct an object of Interface. Also, we cannot instantiate Interface and compiler throws error stating below reason
Compile-time error: “Cannot instantiate the type <Interface-name>”
Question arises, who is going to provide concrete implementations to these abstract methods and how to access “static” variables,
- All implementing classes must provide concrete implementation to all abstract methods declared inside interface
- To access constants, use Interface name for example <Interface-name>.<variables-name>
Example to demonstrate implementation of abstract methods and accessing constants
DemoInterfaceImpl.java
package in.bench.resources.itf.example;
interface DemoInterface {
int AGE = 2;
String NAME = "BenchResources.Net";
void publishArticles();
}
public class DemoInterfaceImpl implements DemoInterface {
@Override
public void publishArticles() {
System.out.println("Age : " + DemoInterface.AGE);
System.out.println("Name : " + DemoInterface.NAME);
}
public static void main(String[] args) {
DemoInterfaceImpl demo = new DemoInterfaceImpl();
demo.publishArticles();
}
}
Output:
Age : 2
Name : BenchResources.Net
All points discussed stand true for interface even in Java 8. But with the release of Java 8, some new and exciting featured are added
One such feature is defining concrete methods inside Interface i.e.;
- default method (prefixing with default keyword)
- static method (prefixing with static keyword)
Note: Prior to Java 8 release, only abstract methods are allowed in interface
1. Need of introducing “default” method in Interface
Declaring methods inside interface, makes implementing classes to provide concrete implementation or else make implementing class as abstract
Which means we got two options while implementing interface i.e.;
- implement all abstract methods
- declare class as abstract, if we want to go for partial implementation
Even if we declare one more abstract method in interface, it becomes quite cumbersome for all implementer classes to implement abstract method forcefully (Really, no choice huh!!)
Q) What if there are more than 100 classes implementing this interface ?
- Till now only solution is to make our hands dirty by implementing abstract method or making implementing classes as abstract (both are forceful action on developer end)
- But with the release Java 8, the new cool feature is added i.e.; if any new method need to be added then provide default implementation for this new method inside interface itself
- This new method will be prefixed with “default” keyword and known as default method in Java 8
- In Java 8, default methods are alternatively referred as Virtual Extension methods or defender methods for their role in interface
- Now implementing classes can override & provide more specific implementation, if required or else they can still use default implementation provided from interface
- This way, new method added inside interface doesn’t forces developer to implement rather it provides default implementation and all implementer classes can relax and whenever required can override & provide implementation
- Note: This cool feature is added to achieve loose coupling with interface and backward compatibility
Let us see an example for default method
InterfaceInJava8.java
package in.bench.resources.itf.example;
// only public and abstract are permitted
public interface InterfaceInJava8 {
// old abstract method
void displayAbstractMethod(); // by default, this is public and abstract
// default method with concrete implementation from Java 8
default void displayDefaultMethod() {
System.out.println("InterfaceInJava8 : default method impl inside Java Interface");
}
}
TestJava8InterfaceImpl.java
package in.bench.resources.itf.example;
public class TestJava8InterfaceImpl implements InterfaceInJava8 {
// similar to abstract method, we can override default method too
@Override
public void displayAbstractMethod() {
System.out.println("TestJava8InterfaceImpl : Implementing abstract method in this class\n");
}
public static void main(String args[]){
// creating an object
TestJava8InterfaceImpl impl = new TestJava8InterfaceImpl();
// invoking abstract method implementation in this class
impl.displayAbstractMethod();
// invoking default method from interface
impl.displayDefaultMethod();
}
}
Output:
TestJava8InterfaceImpl : Implementing abstract method in this class
InterfaceInJava8 : default method impl inside Java Interface
But its look more like an abstract class i.e.; having both abstract and concrete methods, then why there is a need to introduce new “default” method in Java 8
2. Abstract class v/s Interface in Java 8
- At a very high level, it looks very similar but actually they are different in many ways.
- Also, considering the fact that default method in interface helps us to achieve loose coupling and backward compatibility
Sr. No. | Abstract Classes | Interface |
1 | Contains members variables | All variables are actually constants |
2 | It can have constructors | Interface cannot have constructors |
3 | Can hold state of an object using instance member variables | Since, all variables are static and final therefore no concept of holding state of an object |
4 | Forces to implement abstract methods or else declare class as abstract | default methods can be overridden, if required but never forces |
3. Overriding or Implementing default method
- As we all know, interface implementing class needs to provide concrete implementation for all abstract methods but can leave out default methods since there is always default implementation
- But as we seen above, if it’s required to provide more specific implementation then we can override default method
Let us see an example for this case
InterfaceInJava8.java
package in.bench.resources.itf.example;
// only public &amp; abstract are permitted
public interface InterfaceInJava8 {
// old abstract method
void displayAbstractMethod(); // by default, this is public and abstract
// default method with concrete implementation from Java 8
default void displayDefaultMethod() {
System.out.println("InterfaceInJava8: default method impl inside Java Interface");
}
}
TestJava8InterfaceImpl.java
package in.bench.resources.itf.example;
public class TestJava8InterfaceImpl implements InterfaceInJava8 {
// overriding default method to provide specific implementation
public void displayDefaultMethod() {
System.out.println("TestJava8InterfaceImpl : overriding default method from interface\n");
}
// implementing abstract method
@Override
public void displayAbstractMethod() {
System.out.println("TestJava8InterfaceImpl : Implementing abstract method in this class\n");
}
public static void main(String args[]){
// creating an object
TestJava8InterfaceImpl impl = new TestJava8InterfaceImpl();
// invoking abstract method implementation in this class
impl.displayAbstractMethod();
// this times, invokes overriding default method in this class
impl.displayDefaultMethod();
}
}
Output:
TestJava8InterfaceImpl : Implementing abstract method in this class
TestJava8InterfaceImpl : overriding default method from interface
Note: While overriding, cannot reduce the visibility of the inherited method
4. Multiple inheritance problem and its solution
- Again as we all know, Java doesn’t allow to extend multiple classes as it lead to classic diamond problem and happily allows to implement multiple interfaces
- But this leads to ambiguity problem due to default methods in interface
Let us analyze ambiguity problem and later will find solution
Here, in the above example,
- there are two interfaces with exactly same default methods (same signature)
- a class implementing both interfaces
DemoInterfaceA.java
package in.bench.resources.itf.example;
public interface DemoInterfaceA {
// default method with concrete implementation from Java 8
default void displayDefaultMethod() {
System.out.println("DemoInterfaceA : default method impl inside Java Interface");
}
}
DemoInterfaceB.java
package in.bench.resources.itf.example;
public interface DemoInterfaceB {
// default method with concrete implementation from Java 8
default void displayDefaultMethod() {
System.out.println("DemoInterfaceB : default method impl inside Java Interface");
}
}
TestMultipleInheritance.java
package in.bench.resources.itf.example;
public class TestMultipleInheritance implements DemoInterfaceA, DemoInterfaceB {
}
Compile-time error: Duplicate default methods named displayDefaultMethod with the parameters () and () are inherited from the types DemoInterfaceB and DemoInterfaceA
4.1 Solution for multiple inheritance:
While implementing both interfaces, just provide empty implementation to resolve ambiguity problem
Now provide implementation for this method in below ways,
- altogether new implementation
- invoke default implementation either of the interface
- invoke default implementation of both interface (consider sequence while doing so)
- or mix of all above points
Let us see an example for this case
Solution A: Invoke one of the default method from implementing interface using super keyword
TestMultipleInheritance.java
Syntax: <InterfaceName>.super.<defaultMethodName>
package in.bench.resources.itf.example;
public class TestMultipleInheritance implements DemoInterfaceA, DemoInterfaceB {
// overriding default method with new concrete implementation
public void displayDefaultMethod() {
// invoking DemoInterfaceA's default method to resolve ambiguity problem
DemoInterfaceA.super.displayDefaultMethod();
}
public static void main(String args[]) {
TestMultipleInheritance mul = new TestMultipleInheritance();
mul.displayDefaultMethod();
}
}
Output:
DemoInterfaceA : default method impl inside Java Interface
Solution B: Provide new implementation for overriding default method
TestMultipleInheritance.java
Just write new logic for this overriding method
package in.bench.resources.itf.example;
public class TestMultipleInheritance implements DemoInterfaceA, DemoInterfaceB {
// overriding default method with new concrete implementation
public void displayDefaultMethod() {
System.out.println("TestMultipleInheritance : overriding default method" +
"with new concrete implementation");
}
public static void main(String args[]) {
TestMultipleInheritance mul = new TestMultipleInheritance();
mul.displayDefaultMethod();
}
}
Output:
TestMultipleInheritance : overriding default method with new concrete implementation
4.2 Points to remember about default method in interface:
- default methods are alternatively referred as Virtual Extension methods or defender methods
- This could be used as utility methods
- default method supports lambda expression which is again a new feature in Java 8
5. Need of introducing “static” method in interface
- In addition to default methods, Java 8 introduces defining static method inside Interface
- These static methods will act as helper methods and we can organize static methods inside an interface rather to any separate class
Let us see an example for static method
InterfaceInJava8.java
package in.bench.resources.itf.example;
// only public & abstract are permitted
public interface InterfaceInJava8 {
// old abstract method
void displayAbstractMethod(); // by default, this is public and abstract
// static method with concrete implementation from Java 8
static void displayStaticMethod() {
System.out.println("InterfaceInJava8 : static method impl inside Java Interface");
}
}
TestJava8InterfaceImpl.java
- To invoke static method from interface, use interface name
- Syntax: <Interface-Name>.<static-method-name>
package in.bench.resources.itf.example;
public class TestJava8InterfaceImpl implements InterfaceInJava8 {
// implementing abstract method
@Override
public void displayAbstractMethod() {
System.out.println("TestJava8InterfaceImpl : Implementing abstract method in this class\n");
}
public static void main(String args[]){
// creating an object
TestJava8InterfaceImpl impl = new TestJava8InterfaceImpl();
// invoking abstract method implementation in this class
impl.displayAbstractMethod();
// invoking static method using Interface name
InterfaceInJava8.displayStaticMethod();
}
}
Output:
TestJava8InterfaceImpl : Implementing abstract method in this class
InterfaceInJava8 : static method impl inside Java Interface
5.1 Point to remember about static methods in interface:
- These static methods will act as helper method
- This makes easier for us to organize helper methods specific to interface rather to any separate class
- This way, static methods are belong to interface rather to implementing classes
- Cannot override these static methods
Related Articles:
- Java Constructor with example
- Default constructor
- Parametrized constructor
- Default constructor v/s Parametrized constructor
- Constructor overloading
- Constructor chaining
- Constructor v/s Methods
- Private Constructor
- Static constructor in Java – A big interview question ?
References:
- http://docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html
- http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
- http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
- http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html#static
- https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
Happy Coding !!
Happy Learning !!