Default Method

1
2
3
interface A {
void show();
}
interface A {
void show();
}

Is it ‘A’ is the valid interface ?
Yes since it has only abstract method.

1
2
3
4
5
interface B {
void show(){
System.out.println(“show”);
}
}
interface B {
void show(){
System.out.println(“show”);
}
}

Is it ‘B’ is the valid interface ?
No because interface should have only method declarations but not definitions.

Now lets create interface C

1
2
3
4
5
6
interface  C {
void show();
default  void print(){
System.out.println(“print”);
}
}
interface  C {
void show();
default  void print(){
System.out.println(“print”);
}
}

Is it ‘C’ is the valid interface ?

No it is invalid till Java 7 and yes it is valid in Java8.

Yes from Java 8 onwards Interface can have any number of method definitions inside it.

But only constraint is all defined methods must be ‘default’ methods which means while defining methods ‘default’ keyword should be used before the method signature.

Need for default methods in Java ?
Multiple inheritance default method
Let’s assume we have an interface ‘Calculator’ in our application

1
2
3
4
5
6
7
8
9
package com.kb.DefaultMethods;
 
public interface Calculator {
    int add(int a, int b);
    int sub(int a, int b);
    int multiply(int a, int b);
    int divide(int a, int b);
    
}
package com.kb.DefaultMethods;

public interface Calculator {
	int add(int a, int b);
	int sub(int a, int b);
	int multiply(int a, int b);
	int divide(int a, int b);
	
}

Assume we have 3 classes implementing this interface
1)SimpleCalculator and 2)ScientificCalculator 3) SimplePlusFactorialCalculator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.kb.DefaultMethods;
 
public class SimpleCalculator implements Calculator {
 
    @Override
    public int add(int a, int b) {
        
        return a+b;
    }
 
    @Override
    public int sub(int a, int b) {
        return a-b;
    }
 
    @Override
    public int multiply(int a, int b) {
        return a*b;
    }
 
    @Override
    public int divide(int a, int b) {
        return a/b;
    }
 
}
package com.kb.DefaultMethods;

public class SimpleCalculator implements Calculator {

	@Override
	public int add(int a, int b) {
		
		return a+b;
	}

	@Override
	public int sub(int a, int b) {
		return a-b;
	}

	@Override
	public int multiply(int a, int b) {
		return a*b;
	}

	@Override
	public int divide(int a, int b) {
		return a/b;
	}

}

ScientificCalculator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.kb.DefaultMethods;
 
public class ScientificCalculator implements Calculator {
 
    @Override
    public int add(int a, int b) {
 
        return a + b;
    }
 
    @Override
    public int sub(int a, int b) {
        return a - b;
    }
 
    @Override
    public int multiply(int a, int b) {
        return a * b;
    }
 
    @Override
    public int divide(int a, int b) {
        return a / b;
    }
 
// rest other methods for scientific calculator
}
package com.kb.DefaultMethods;

public class ScientificCalculator implements Calculator {

	@Override
	public int add(int a, int b) {

		return a + b;
	}

	@Override
	public int sub(int a, int b) {
		return a - b;
	}

	@Override
	public int multiply(int a, int b) {
		return a * b;
	}

	@Override
	public int divide(int a, int b) {
		return a / b;
	}

// rest other methods for scientific calculator
}

SimplePlusFactorialCalculator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.kb.DefaultMethods;
 
public class SimplePlusFactorialCalculator implements Calculator {
 
    @Override
    public int add(int a, int b) {
 
        return a + b;
    }
 
    @Override
    public int sub(int a, int b) {
        return a - b;
    }
 
    @Override
    public int multiply(int a, int b) {
        return a * b;
    }
 
    @Override
    public int divide(int a, int b) {
        return a / b;
    }
// rest other methods for SimplePlusFactorialCalculator calculator 
}
package com.kb.DefaultMethods;

public class SimplePlusFactorialCalculator implements Calculator {

	@Override
	public int add(int a, int b) {

		return a + b;
	}

	@Override
	public int sub(int a, int b) {
		return a - b;
	}

	@Override
	public int multiply(int a, int b) {
		return a * b;
	}

	@Override
	public int divide(int a, int b) {
		return a / b;
	}
// rest other methods for SimplePlusFactorialCalculator calculator 
}

Now assume we need to add new method factorial () method in our interface to provide this method’s definition to few of the subclasses, in our example it is SimplePlusFactorialCalculator and ScientificCalculator but not SimpleCalculator
How can we do it ?
We need to add it in interface but once we add its declaration in interface , what is the consequence on all the implemented classes?
Yes we need to implement in all the implemented classes including those classes which does not require that method(in our example it is SimpleCalculator). So what if 1000 such classes implements this interface, then all 1000 classes needs to be changed which is not good all the time because some classes need it and some classes may not need it.
So java 8 feature ‘default method’ will resolve this kind of backward compatibility problem easily without changing the irrelevant sub classes.
Steps to resolve using default method
Step 1 – add a method definition inside the interface but prefix signature with default keyword.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.kb.DefaultMethods;
 
public interface Calculator {
    int add(int a, int b);
    int sub(int a, int b);
    int multiply(int a, int b);
    int divide(int a, int b);
    
    default int factorial(int n){
          int result = 1;
           for (int i = 1; i <= n; i++) {
               result = result * i;
           }
           return result;
    }
    
}
package com.kb.DefaultMethods;

public interface Calculator {
	int add(int a, int b);
	int sub(int a, int b);
	int multiply(int a, int b);
	int divide(int a, int b);
	
	default int factorial(int n){
		  int result = 1;
	       for (int i = 1; i <= n; i++) {
	           result = result * i;
	       }
	       return result;
	}
	
}

Step2 – No code change is required in any of the inherited classes. All inherited classes will have the default method definition available to them.
Now write client code as below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.kb.DefaultMethods;
 
public class CalculatorClient {
 
    public static void main(String[] args) {
        Calculator calc = new SimplePlusFactorialCalculator();
        int res1 = calc.factorial(5);
        System.out.println(res1);
        
        SimplePlusFactorialCalculator calculator = new SimplePlusFactorialCalculator();
        int res2 = calculator.factorial(6);
        System.out.println(res2);
    }
 
}
package com.kb.DefaultMethods;

public class CalculatorClient {

	public static void main(String[] args) {
		Calculator calc = new SimplePlusFactorialCalculator();
		int res1 = calc.factorial(5);
		System.out.println(res1);
		
		SimplePlusFactorialCalculator calculator = new SimplePlusFactorialCalculator();
		int res2 = calculator.factorial(6);
		System.out.println(res2);
	}

}

It will work 100% without changing any implemented classes.

Output is

So any number of default methods can be added to interface and every default method should have a body.

Multiple inheritance in Java with default methods
diagram

Let’s create parent1 and parent2 classes and implementing child

1
2
3
4
5
6
7
8
package com.kb.DefaultMethods;
 
public interface Parent1 {
    default void show(){
        System.out.println("show from parent1");
    }
 
}
package com.kb.DefaultMethods;

public interface Parent1 {
	default void show(){
		System.out.println("show from parent1");
	}

}

Parent2.java

1
2
3
4
5
6
7
package com.kb.DefaultMethods;
 
public interface Parent2 {
    default void show(){
        System.out.println("show from parent1");
    }
}
package com.kb.DefaultMethods;

public interface Parent2 {
	default void show(){
		System.out.println("show from parent1");
	}
}

Child.java

1
2
3
4
5
package com.kb.DefaultMethods;
 
public class Child implements Parent1,Parent2 {
 
}
package com.kb.DefaultMethods;

public class Child implements Parent1,Parent2 {

}

This child class will not compile because of the duplicate methods inherited from both parent1 and parent2.
Its equivalent to as below

1
2
3
4
5
6
7
8
9
10
11
12
package com.kb.DefaultMethods;
 
public class Child implements Parent1,Parent2 {
    public void show(){
        System.out.println("show from parent1");
    }
    
    public void show(){
        System.out.println("show from parent2");
    }
    
}
package com.kb.DefaultMethods;

public class Child implements Parent1,Parent2 {
	public void show(){
		System.out.println("show from parent1");
	}
	
	public void show(){
		System.out.println("show from parent2");
	}
	
}

So this can be resolved only by overrding show() method once in a child class.
Below child class will compile

1
2
3
4
5
6
7
8
package com.kb.DefaultMethods;
 
public class Child implements Parent1,Parent2 {
    public void show(){
        System.out.println("show from child");
    }
    
}
package com.kb.DefaultMethods;

public class Child implements Parent1,Parent2 {
	public void show(){
		System.out.println("show from child");
	}
	
}

Difference between Interface with default methods and abstract class

In Java 8 we can declare as well as define methods within interfaces as we discussed so far....
but how it is different from Abstract classes ? we can do the same with abstract class
Abstract class can not be instantiated (i.e. objects can not be created for it) and which may contain method bodies.
So abstract class and interface with default method both are same right ?
No. they are not same and not one is the replacement of other. Each will serve its own purpose.
. Abstract class can have constructors and member variables. Whereas interfaces with Java 8 default methods cannot. It cannot have constructors and member variables.
Default method should be used for backward compatibility which means whenever we want to add additional functionality in an existing legacy interface, we can use default methods without breaking any existing implementer classes but same cannot be achieved with abstract classes which forces sub classes to adopt the change.

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on