Java 8 Default Methods Tutorial
Interfaces in Java always contained method declaration not their 
definitions (method body). There was no way of defining method body / 
definition in interfaces. This is because historically Java didn’t allow
 multiple inheritance of classes. It allowed multiple inheritance of 
interfaces as interface were nothing but method declaration. This solves
 the problem of ambiguity in multiple inheritance. Since Java 8 it is 
now possible to add method bodies in interfaces. 
Java 8 has a new feature called Default Methods. It is now possible to add method bodies into interfaces! 
public interface Math {
	int add(int a, int b);
	default int multiply(int a, int b) {
		return a * b;
	}
}
In above Math interface we added a method multiply with actual method body.
Why we need Default Methods?
Why would one want to add methods into Interfaces? We’ll it is 
because interfaces are too tightly coupled with their implementation 
classes. i.e. it is not possible to add a method in interface without 
breaking the implementor class. Once you add a method in interface, all 
its implemented classes must declare method body of this new method. 
Since Java 8, things started getting ugly. A new feature Lambda was 
introduce which is cool. However it is not possible to use this feature 
in existing Java libraries such as java.util package. If you add a 
single method in interface 
List, it breaks everything. You need to add its implementation in every class that implements List interface. Imagine in real world how many custom classes would change.
So for backward compatibility, Java 8 cleverly added Default Methods. 
Virtual Extension Methods
It added a new concept Virtual extension methods, or as they are often called defender methods,
 can now be added to interfaces providing a default implementation of 
the declared behavior. So existing interfaces can be augmented without 
compromising backward compatibility by adding extension methods to the 
interface, whose declaration would contain instructions for finding the 
default implementation in the event that implementors do not provide a 
method body. A key characteristic of extension methods is that they are 
virtual methods just like other interface methods, but provide a default
 implementation in the event that the implementing class does not 
provide a method body.
Consider following example:
interface Person {
	//adds a java 8 default method
	default void sayHello() {
		System.out.println("Hello there!");
	}
}
class Sam implements Person {
}
public class Main {
	
	public static void main(String [] args) {
		
		Sam sam = new Sam();
		
		//calling sayHello method calls the method
		//defined in interface
		sam.sayHello();
	}
}
Output:
Hello there!
In above code we added a defender method 
sayHello() in Person interface. So it was ok for class Sam to avoid declaring this methods body.What about Multiple Inheritance?
Adding method definitions in interfaces can add ambiguity in multiple
 inheritance. isn’t it? Well, it does. However Java 8 handle this issue 
at Compile type. Consider below example:
interface Person {
	default void sayHello() {
		System.out.println("Hello");
	}
}
interface Male {
	default void sayHello() {
		System.out.println("Hi");
	}
}
class Sam implements Person, Male {
}
In this example we have same defender method sayHello in both 
interfaces Person and Male. Class Sam implements these interfaces. So 
which version of sayHello will be inherited? We’ll if you try to compile
 this code in Java 8, it will give following error.
class Sam inherits unrelated defaults for sayHello() from types Person and Male class Sam implements Person, Male { ^ 1 error
So that solves multiple inheritance problem. You cannot implement multiple interfaces having same signature of Java 8 default methods (without overriding explicitly in child class). 
We can solve the above problem by overriding sayHello method in class 
Sam.interface Person {
	default void sayHello() {
		System.out.println("Hello");
	}
}
interface Male {
	default void sayHello() {
		System.out.println("Hi");
	}
}
class Sam implements Person, Male {
	
	//override the sayHello to resolve ambiguity
	void sayHello() {
	
	}
}
It is also possible to explicitly call method from child class to parent interface. Consider in above example you want to call 
sayHello method from Male interface when Sam.sayHello is called. You can use super keyword to explicitly call the appropriate method.class Sam implements Person, Male {
	
	//override the sayHello to resolve ambiguity
	void sayHello() {
		Male.super.sayHello();
	}
}
Difference between default methods and abstract class
Ok, so far it looks good. In Java 8 we can have concrete methods 
within interfaces.. right.. So how it is different from Abstract 
classes? Remember an abstract class is a class that can not be 
instantiated (i.e. objects can not be created of) and which may contain 
method bodies. Default method in Java 8 looks similar to Abstract class 
isn’t it?
We’ll its different actually. Abstract class can hold state of 
object. It can have constructors and member variables. Whereas 
interfaces with Java 8 default methods cannot hold state. It cannot have
 constructors and member variables. You should still use Abstract class 
whenever you think your class can have state or you need to do something
 in constructor. Default method should be used for backward 
compatibility. Whenever you want to add additional functionality in an 
existing legacy interface you can use default methods without breaking 
any existing implementor classes.
Also abstract classes cannot be root classes in Lambda expression. 
What?… I know that’s confusing, but Lambda expressions are the reason 
why virtual extension methods were introduced in Java 8. When a lambda 
expression is evaluated, the compiler can infers it into the interface 
where default method is added. 

Comments
Post a Comment