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?
The key technical differences between an abstract class and an interface are: Abstract classes can have constants, members, method stubs (methods without a body) and defined methods, whereas interfaces can only have constants and methods stubs.
Abstract Class Vs. Interface: Explore the Difference between Abstract Class and Interface in Java. The Abstract class and Interface both are used to have abstraction. An abstract class contains an abstract keyword on the declaration whereas an Interface is a sketch that is used to implement a class.
Note that from Java 8 onwards, we can create default and static methods in interface that contains the method implementations. Abstract classes can have constructors but interfaces can't have constructors. Abstract class have all the features of a normal java class except that we can't instantiate it.
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.
There have been some very detailed answers, but they seem to be missing one point that I at least consider as one of the very few justifications to have abstract classes at all:
Abstract classes can have protected members (and members with default visibility). Methods in interfaces are implicitly public.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With