Many concepts in Java are derived from real-world scenarios. Interfaces as well. If you want to turn on a television, you need to press the power button. This button is the interface between you and the electronics inside the television. Java interfaces have the same behaviour as real-world interfaces (e.g., a television interface): they set strict rules (a blueprint, if you will) on how to interact with objects. As you have already learned, these strict rules can be defined with methods. In fact, Java objects define their interaction with the outside world through the methods that they expose.

In a nutshell, an Interface in Java is an abstract type used to specify how the outside world can interact with the objects that implement the interface.


How to create an Interface?

You create them as you create classes, but you must use the keyword interface instead of class.

Going back to our example with the television, let’s create an Interface called Television with two methods pressOnButton() and pressOffButton()

public interface Television {
    public void pressOnButton();
    public void pressOffButton();
}

The methods pressOnButton(); pressOffButton(); have no body (i.e., no {})—they just end with ;—they are by default abstract. In a nutshell, a Java interface represents a group of (abstract) methods with no bodies.


How to implement an Interface?

Now, we will create a class that implements our interface. Yes, a class does not extends an interface (like we did with classes), it implements it. For example, let’s create a class LCDTelevision.

public class LCDTelevision implements Television {

    @Override
    public void pressOnButton() {
        System.out.println("The television is on");
    }

    @Override
    public void pressOffButton() {
        System.out.println("The television is off");
    }

}

We use the implements keyword in the class declaration. The class gives a compilation error if we do not override the methods declared in the interface Television. The interface Television gives the methods that all the classes that implement a Television must have. In our example, the pressOnButton()and pressOffButton() methods.

Now, if we want to instantiate an object LCDTelevision we can do:

    public static void main(String[] args) {
        Television lcdTv = new LCDTelevision();
        lcdTv.pressOnButton();
        System.out.println("I am watching TV....");
        lcdTv.pressOffButton();
    }

Note that, interfaces like abstract classes cannot be instantiated (we cannot do Television tv = new Television(); ) we must specify the implementation we want: Television lcdTv = new LCDTelevision()).


A note on code style

Please note that the declared type of lcdTv is Television not LCDTelevision. We could have also used LCDTelevision as the type of lcdTv(i.e., LCDTelevision lcdTv = new LCDTelevision();). This would have worked fine.

However, depending on the situation, often it might be handy to store the reference of an object that implements an interface I with a variable of type I. This often leads to more maintainable code.

For example, it is considered good style to store a reference to a JDK ArrayList or LinkedList in a variable of type List. List is a common interface of both ArrayList and LinkedList.


    public static void main(String[] args) {
        List<String> names = new ArrayList<String>();
        createNames(names);                                    
    }

    public static void createNames(List<String> names){
        // some code
    }


In this way, if later you decide to use LinkedList instead of an ArrayList you just need to change one line of code: List<String> names = new ArrayList<String>(); to List<String> names = new LinkedList<String>();. You do not need to change other lines of code that use the list names. For example, you do not need to change the method declaration of method createNames. Conversely, you must do it if the object’s reference was of type ArrayList.


    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<String>();
        createNames(names);
    }

    public static void createNames(ArrayList<String> names){
        // some code
    }


Note that, in both cases: List<String> names = new ArrayList<String>(); and ArrayList<String> names = new ArrayList<String>();, the names reference variable points to an object of type ArrayList. It is only the type of the reference that is in one case List and in the other ArrayList.


What is the difference between an abstract class and an interface?

I believe that right now, you are wondering what is the difference between an abstract class and an interface. You can think about interfaces as being “a really really abstract abstract class. So abstract that it’s no longer a class – it’s now just an interface. An interface does not have any implementation in it. The table below summarizes the key differences between interfaces and abstract classes.

Property Interface Abstract class
Multiple Inheritance A class can implement several Interfaces A class can extend only one abstract class
Contains Abstract methods Abstract methods and/or concrete methods
When to use It is better to use interfaces when various implementations share only method signatures. It should be used when various implementations of the same kind share a common behavior.
Implementation An interface is abstract so that it cannot provide any implemented functionality. An abstract class can give implementation that can be overridden.
Inheritance An interface can inherit multiple interfaces but cannot inherit a class. An abstract class can inherit a class and multiple interfaces.
Constructor An interface cannot declare constructors An abstract class can declare constructors
Abstract keyword In an interface, the abstract keyword is optional for declaring a method as abstract. In an abstract class, the abstract keyword is compulsory for declaring a method as abstract.
Class type An interface can have only public abstract methods. An abstract class can have protected abstract methods and public abstract methods.

One of the key differences between interfaces and abstract classes is that you can implement more than one interface in one class (you cannot do this with abstract classes). You just need to separate the interface names with commas in the class declaration. For example, let’s say that we have an interface ElectricalAppliance defined as:

public interface ElectricalAppliance  {
    public void plugIn();
    public void plugOut();
}

Then, our LCDTelevision can implement both interfaces: ElectricalAppliance and Television. Note that in this case, the LCDTelevision class has to provide the implementation of all four methods: pressOnButton, pressOffButton, plugIn, and plugOff.

public class LCDTelevision implements Television, ElectricalAppliance {

    @Override
    public void pressOnButton() {
        System.out.println("The television is on");
    }

    @Override
    public void pressOffButton() {
        System.out.println("The television is off");
    }

    @Override
    public void plugIn() {
        System.out.println("The television is plug into an electricity supply");
    }

    @Override
    public void plugOff() {
        System.out.println("The television is plug off an electricity supply");
    }

}


Why does Java need interfaces to support “multiple inheritance”? Why can’t a class extend multiple classes?

Java does not support “multiple inheritance” (a class can only inherit from one superclass). However, “multiple inheritance” can be achieved with interfaces—a class can implement multiple interfaces.

You might wonder why multiple inheritance is possible with interfaces but not with classes? The answer is because of ambiguity. Two classes might have different implementations of the same method or might have two different functionalities with the same method name.

For example, let’s assume that Java allows multiple inheritance with classes.

class A {

    public void run() {
        System.out.println("A");
    }

}

class B {

    public void run() {
        System.out.println("B");
    }

}

public class MyClass extends A, B { // ATTENTION extending two classes is not allowed
    // we do it just for making a point :)

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.run(); // Which method should I execute?
    }
}

Should the program print “A” or “B”? The JVM would not be able to decide which method to execute. There is ambiguity. However, there is no ambiguity if we use interfaces. It is because the implementation of the methods is never specified in interfaces. Interfaces specify only what the class is doing, not how it is doing it. How it is doing it must be specified by the class that implements the interface. For example, if we use interfaces, even if two interfaces have the same method names, there is no conflict or ambiguity. This is because it is MyClass that defines the implementation.

interface A {
    public void run();
}

interface B {
    public void run();
}

public class MyClass implements A, B {

    @Override
    public void run() {
        System.out.println("A");
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.run();
    }

}


Can I have an “empty” interface that does not declare any methods?

Yes, you can! Is it something useful? Yes, indeed. For example, let’s say that we want to create a List that contains Vehicles. Vehicles can be very different so I don’t expect that they can share functionalities. So we can use interfaces to just tell the JVM that the List can only contain Vehicle objects.

import java.util.ArrayList;
import java.util.List;

interface Vehicle {
    // empty interface
}

class Car implements Vehicle {
    public void drive(int speed) {
        // some implementation
    }
}

class Airplane implements Vehicle {
    public void fly(int speed, int altitude) {
        // some implementation
    }
}

class Boat implements Vehicle {
    public void sail(int direction, int speed) {
        // some implementation
    }
}

public class MyClass {
    public static void main(String[] args) {
        List<Vehicle> vehicles = new ArrayList<Vehicle>();
        vehicles.add(new Car());
        vehicles.add(new Airplane());
        vehicles.add(new Boat());
    }
}


Can an interface inherit from another interface?

Yes, but instead of using implements you will use extends. In fact: a class extends another class, an interface extends another interface, but a class implements an interface.

For example you can do:

interface A {
    public void funcA();
}

interface B extends A {
    public void funcB();
}

class C implements B {

    @Override
    public void funcA() {
        System.out.println("Implementation function A");
    }

    @Override
    public void funcB() {
        System.out.println("Implementation function B");
    }
}

In this case, the class C must implement both method funcA and funcB.


(Summary) Key Facts about Interfaces:

  • Interface is a fundamental concept in Java OOP. It is used to achieve abstraction and multiple inheritance.
  • Java Interface also represents the IS-A relationship.
  • Like abstract classes, interfaces cannot be used to create objects (in the example above, it is not possible to instantiate a “Television” object).
  • Interface methods do not have a body - the body is provided by the “implement” class
  • An interface cannot contain a constructor (as it cannot be used to create objects)
  • If a class implements an interface, it must implement all of the interface’s methods
  • Interface methods are by default abstract and public
  • Interface attributes are by default public, static and final


Edit Get your hands dirty!

You are hiking in the forest, and you come across interesting items that you are allowed to gather and put in your backpack. Some items are eatable, some are not.

import java.util.ArrayList;
import java.util.List;

public class Mushroom {

	private boolean isPoisonous() {
		System.out.println("check online if it is poisonous...");
		return false; // let's assume it is not
	}

	public void eat() {
		if (!isPoisonous()) {
			System.out.println("eating the mushroom");
		}
	}
}

public class Apple {

	private void peal() {
		System.out.println("pealing the apple");
	}

	public void eat() {
		peal();
		System.out.println("eating the apple");
	}
}

public class Strawberry {

	private void wash() {
		System.out.println("wash the strawberry");
	}

	public void eat() {
		wash();
		System.out.println("eating the strawberry");
	}
}

public class Stone {

	public void examine() {
		System.out.println("examining the stone");
	}

}

public class WoodenStick {

	public void use() {
		System.out.println("use wooden stick to walk");
	}

}


After a while, you feel hungry, and you want to eat all the eatable objects that you have found.

public class Main {

	public static void main(String[] args) {
		List<Object> backpack = new ArrayList<Object>();

		System.out.println("Walking in the forest...");
		System.out.println("I found a beautiful stone...");
		backpack.add(new Stone());
		System.out.println("I found a bush with 10 strawberries");
		for (int i = 0; i < 10; i++) {
			backpack.add(new Strawberry());
		}
		System.out.println("I found a wooden stick");
		backpack.add(new WoodenStick());
		System.out.println("I found 3 mushrooms and 1 apple");
		backpack.add(new Mushroom());
		backpack.add(new Mushroom());
		backpack.add(new Mushroom());
		backpack.add(new Apple());
		System.out.println("another beautiful stone...");
		backpack.add(new Stone());

		System.out.println("I am tired and hungry");
		System.out.println();

		System.out.println(" I want to eat all the eatable items that I found");
		for (Object item : backpack) {
			if (item instanceof Strawberry) {
				((Strawberry) item).eat();
			} else if (item instanceof Apple) {
				((Apple) item).eat();
			} else if (item instanceof Mushroom) {
				((Mushroom) item).eat();
			}
		}
	}

}

The problem with this implementation is that if later on, we find new types of eatable objects (blueberries, walnuts, … ) we need to add other else if conditions that would make the code verbose and difficult to maintain and modify. Let’s use interfaces to improve the design of our program!

Edit the Repl, which contains the code above, as follows:

  1. Create one interface FoundObject, all the classes (regardless if they represent eatable objects or not) should implement this interface. Should this interface have methods? Do all the classes have the same functionalities?
  2. Change the type of the list backpack accordingly
  3. Create another interface specif for eatable objects: Eatable. Classes that represent eatable objects should also implement this interface. Is there are any functionality common to all Eatable object?
  4. Change the body of the for loop. Still, we should eat only eatable objects. (HINT: you should use instance of only once).
  5. BONUS Can you modify the program so that we still have two interfaces but Eatable extends FoundObject? In this case, does the class Apple need to implement both Eatable and FoundObject interfaces?
  6. BONUS Can you modify the program so that FoundObject has now a weight field?, should you still use interfaces? or now is it better to use abstract classes?