What are the differences between abstract classes and interfaces in Java 8?

David says Reinstate Monica picture David says Reinstate Monica · Mar 23, 2014 · Viewed 19k times · Source

In Java there used to be a subtle but important difference between abstract classes and interfaces: default implementations. Abstract classes could have them, interfaces could not. Java 8 though introduces default implementations for interfaces, meaning this is no longer the critical difference between an interface and an abstract class.

So what is?

As best as I can tell, the only remaining difference (besides perhaps some under the hood efficiency stuff) is that abstract classes follow traditional Java single-inheritance, whereas interfaces can have multiple-inheritance (or multiple-implementation if you will). This leads me to another question -

How do the new Java 8 interfaces avoid the diamond Problem?

Answer

skiwi picture skiwi · Mar 23, 2014

Interfaces cannot have state associated with them.

Abstract classes can have state associated with them.

Furthermore, default methods in interfaces need not be implemented. So in this way, it will not break already existing code, as while the interface does receive an update, the implementing class does not need to implement it.
As a result you may get suboptimal code, but if you want to have more optimal code, then your job is to override the default implementation.

And lastly, in case a diamond problem occurs, then the compiler will warn you, and you will need to choose which interface you want to implement.

To show more about the diamond problem, consider the following code:

interface A {
    void method();
}

interface B extends A {
    @Override
    default void method() {
        System.out.println("B");
    }
}

interface C extends A { 
    @Override
    default void method() {
        System.out.println("C");
    }
}

interface D extends B, C {

}

Here I get the compiler error on interface D extends B, C, that:

interface D inherits unrelated defaults for method() form types B and C

The fix is:

interface D extends B, C {
    @Override
    default void method() {
        B.super.method();
    }
}

In case I wanted to inherit the method() from B.
The same holds for if D were a class.

To show even more about the difference between interfaces and abstract classes in Java 8, consider the following Team:

interface Player {

}

interface Team {
    void addPlayer(Player player);
}

You can in theory provide a default implementation of addPlayer such that you can add players to for example a list of players.
But wait...?
How do I store the list of players?
The answer is that you cannot do that in an interface, even if you have default implementations available.