What is an interface in Java?
The basic role of the interface in Java is to define a set of methods that can be implemented in other classes.
There can be multiple classes that implement the same interface. Then, in run-time, using the reference type of the given interface (polymorphism) will be determined which method will be called.
A class can inherit the properties and behaviours of another class, but, in Java, only single inheritance is possible, which means that a class can only have one superclass.
However, sometimes it is necessary to combine behaviours from two or more classes to achieve the desired functionality.
Considering that only single inheritance is used in Java, the problem of the hierarchy of classes with mixed behaviour is solved using the interface.
Classes inherit the interface using the keyword implements.
Example of declaring an interface in Java:
interface Runnable {}
Example of using the interface:
interface Vehicle { void move(); } class Car implements Vehicle { @Override public void move() { System.out.println("The car is moving..."); } } class Test { public static void main(String[] args) { Vehicle car = new Car(); car.move(); } }
Examples and notes
An interface cannot be instantiated just like an abstract class:
interface Vehicle { void move(); } class Test { public static void main(String[] args) { Vehicle car = new Vehicle(); // DOES NOT COMPILE } }
Before Java 8, interfaces could only contain fields and abstract methods. Since Java 8 and Java 9, we can have default, private and static methods in an interface.
Interface fields are public, static, and final by default, and the methods are public and abstract.
If we do not specify an access modifier or keyword abstract when declaring a method, the java compiler will do it under the hood.
Also, when declaring fields, the compiler will add public, static, and final keywords.
An example where multiple classes inherit the same interface and the use of polymorphism in that case:
interface Vehicle { void move(); } class Car implements Vehicle { @Override public void move() { System.out.println("The car is moving..."); } } class Truck implements Vehicle { @Override public void move() { System.out.println("The truck is moving..."); } } class Test { public static void main(String[] args) { Vehicle car = new Car(); Vehicle truck = new Truck(); car.move(); truck.move(); } }
interface Vehicle { void move(); } interface Runnable { void run(); } class Car implements Vehicle, Runnable { @Override public void move() { System.out.println("Move..."); } @Override public void run() { System.out.println("Run..."); } } class Test { public static void main(String[] args) { Car car = new Car(); car.move(); car.run(); } }
interface Vehicle { String brand = "Ford"; default void move() { System.out.println("The vehicle is moving..."); } static String returnBrand() { return brand; } } class Car implements Vehicle { } class Test { public static void main(String[] args) { Vehicle car = new Car(); car.move(); System.out.println(Vehicle.returnBrand()); } }
interface Runnable { void run(); } interface Vehicle extends Runnable { } class Car implements Vehicle { @Override public void run() { System.out.println("Run..."); } } class Test { public static void main(String[] args) { Vehicle car = new Car(); car.run(); } }