Summary: in this tutorial, you’ll learn about Java interface default methods, including their syntax, usage, and some best practices.
Introduction to Java interface default methods
In Java, an interface defines a contract that classes must adhere to. If you want to add new methods to an interface that is already implemented by multiple classes, you need to modify the classes and provide the implementations for the new methods. Otherwise, the code won’t compile.
To resolve this issue, Java 8 introduced the default methods so that interfaces can have methods with implementations.
Default methods allow you to add new methods to existing interfaces without breaking the classes that already implement them.
Defining Java interface default methods
To define a default method in an interface, you use the default
keyword followed by the method signature and its implementation:
interface MyInterface {
// Abstract method (no implementation required)
void abstractMethod();
// Default method with an implementation
default void defaultMethod() {
// Implementation code goes here
}
}
Code language: Java (java)
In this syntax:
- Use the
default
keyword to define a default method. - The default method always has an implementation. Also, the default method is automatically available in all classes that implement the interface.
- The class that implements the interface can override the default method by providing its own implementation.
- An interface can have a combination of abstract and default methods.
Implementing an interface with default methods
The following shows how to define a class that implements the interface with the default method:
class MyClass implements MyInterface {
@Override
public void abstractMethod() {
System.out.println("Implemented abstractMethod");
}
}
Code language: Java (java)
In this example, the MyClass
can invoke the defaultMethod()
method. Optionally, you can override the default method in the class like this:
class MyClass implements MyInterface {
@Override
public void abstractMethod() {
System.out.println("Implemented abstractMethod");
}
// Optional: Overriding the default method
@Override
public void defaultMethod() {
System.out.println("Custom implementation of defaultMethod");
}
}
Code language: Java (java)
Java interface default methods example
Let’s take an example of using default methods in an interface to understand how they work.
First, define an interface Shape:
interface Shape {
double area();
default void display(){
System.out.println("Shape: " + getClass().getSimpleName());
System.out.println("Area: " + area());
}
}
Code language: Java (java)
The Shape
interface has two methods:
area()
is an abstract method.display()
is a default method.
Any class that implements the Shape
interface must provide an implementation for the area()
method and optionally can override the display()
default method.
Second, define a class Square
that implements the Shape
interface:
class Square implements Shape {
private double length;
public Square(double length){
this.length = length;
}
@Override
public double area() {
return this.length * this.length;
}
}
Code language: Java (java)
The Square
class implements the area()
method and uses the default behavior of the display()
method.
Third, define a class Rectangle
that implements the Shape
interface:
public class Rectangle implements Shape {
private double length;
private double width;
public Rectangle(double length,double width){
this.length = length;
this.width = width;
}
@Override
public double area() {
return this.length * this.width;
}
@Override
public void display(){
System.out.println("***");
System.out.println("Shape: " + getClass().getSimpleName());
System.out.println("Area: " + area());
System.out.println("***");
}
}
Code language: Java (java)
The Rectangle
class implements the area()
method that returns the area of the rectangle. Also, the Rectangle
class overrides the display()
method that provides its own specific implementation.
Fourth, use the Square
and Rectangle
classes in the main()
method of the program:
public class App {
public static void main(String[] args) {
var square = new Square(10);
square.display();
var rectangle = new Rectangle(10, 5);
rectangle.display();
}
}
Code language: Java (java)
Output:
Shape: Square
Area: 100.0
***
Shape: Rectangle
Area: 50.0
***
Code language: Java (java)
When we call the display()
method on the square
object, it uses the default implementation provided by the Shape
interface.
But when we call the display()
method on the rectangle
object, it uses the implementation implemented by the Rectangle
class.
Resolving default method conflict
Java allows a class to implement multiple interfaces. If two interfaces have the same default method, a conflict will occur because the class doesn’t know which default method to use.
Let’s take a look at an example.
Suppose we have an interface called Output
that has a default method display()
:
interface Output {
default void display() {
System.out.println(getClass().getSimpleName());
}
}
Code language: Java (java)
The Square
class implements both Shape
and Output
interfaces:
public class Square implements Shape, Output {
private double length;
public Square(double length){
this.length = length;
}
@Override
public double area() {
return this.length * this.length;
}
}
Code language: Java (java)
Now both display()
methods of the Shape
and Output
interfaces are available in the Square
class. It causes an ambiguous error.
To fix this, you need to explicitly override the display()
method and select which method you want to use.
For example, if you want to use the display()
method from the Shape
interface, you can do it as follows:
package com.javazerotomastery.drawing;
public class Square implements Shape, Output {
private double length;
public Square(double length){
this.length = length;
}
@Override
public double area() {
return this.length * this.length;
}
@Override
public void display() {
Shape.super.display();
}
}
Code language: Java (java)
The Shape.super.display()
calls the display()
method of the Shape
interface.
If you want to use the display()
method of the Output
interface, you need to change the display()
method to the following:
Output.super.display();
Code language: Java (java)
Another option is that you can override the display()
method completely like what the Rectangle class does.
Notice that because the Rectangle
explicitly overrides the display()
default method, it doesn’t have an ambiguous issue.
Summary
- An interface can include both the abstract and the default methods.
- A default method is a method with the
default
keyword and an implementation. - A default method is automatically available in all classes that implement the interface.
- Use default methods to add new functionality to existing interfaces without breaking backward compatibility.
- Classes may override the default method by providing a specific implementation.
- If a class implements two or more interfaces that have the same default method, the class needs to explicitly override the default method.
- Prefer using interfaces for defining contracts and abstract classes for sharing common implementation code among classes.