Interface vs Abstract Class Java Example
In this post, we feature an Interface vs Abstract Class Java Example. One of the most discussed topics in Java for newbies is the Interface and Abstract class. I will give insights into the Java Interfaces and abstract classes. I will also provide some examples and practical use cases.
You can also check the Java Abstract Class Example in the following video:
1. Introduction
Abstraction, Encapsulation, and Inheritance are the basic ingredients of an Object-Oriented Language. Interface and Abstract Classes fall under inheritance.
1.1. Class
Class is the basic structure in the object-oriented language. They provide a blueprint of a real-world object. They contain object attributes and their concrete behaviors (called as methods). A concrete class can be instantiated to create any number of objects.
1.2 Abstract Class
Abstract classes are special form of a class where some of the behaviors (methods) don’t have a concrete definition. These behaviors are just a declaration (these type of methods are called abstract methods). Abstract classes can’t be instantiated. Any of the concrete class should inherit an abstract class and provide a definition of the abstract method. An abstract class can have attributes and access modifiers like a class.
1.3. Interface
Interfaces are another special Object-Oriented structure which contains only abstract methods. They are just like protocols and the implementing classes should provide definition to all the methods in the interfaces. Apart from methods they can have public static variables. Java 8 has enhanced interfaces with additional feature and we will see them later in the article.
2. Interface vs Abstract Class Java Example – Differences
The following table lists the abstract vs interface :
Interface | Abstract class |
Declared as public interface Interface | Declared as public abstract class AbstractClass |
Can contain only abstract methods | Can contain both abstract and non abstract (concrete) methods |
Only public final constants are allowed | Variables/ attributes with all access modifiers (private, protected, public and default) are allowed. It can have both final and static attributes too. |
All methods are public | All the access modifiers are allowed |
Support multiple inheritance | Don’t support multiple inheritance |
Interfaces should be implemented using keyword implements. eg: class ExampleClass implements ExampleInterface | An abstract class can be extended by using the extends keyword. eg: class ExampleClass extends ExampleAbstractClass |
An interface can extend one or more interfaces only | An abstract class can extend another abstract class and can implement one or more interfaces |
Interfaces cannot be instantiated or invoked | Abstract classes cannot be instantiated, but can be invoked if they have main method |
Static methods aren’t allowed in an interface | Both static and non-static methods are allowed |
Even though, abstract classes with only abstract methods and final constants can provide similar feature as interfaces, why Java created interfaces?
Java by default doesn’t support multiple inheritance. One class can extend behavior from only one another class or abstract class. This restriction is applied to avoid Diamond Problem.
“Diamond problem” is the ambiguity problem that arises as a side effect of multiple inheritance. It generally happens in languages that allow multiple inheritance of the state (Ex: C++). Java solves it by not allowing multiple inheritance. Below diagram explains the classic diamond problem. Class A
provides a definition for method m and Class B
and Class C
are derived from A. They both get method m’s implementation from A. Now a new Class D
extends both B and C. This is where the confusion arises, which definition of method m will Class D
get?
Java solves it by using interfaces. Since interfaces don’t provide method definitions, it is the responsibility of the implementing class to provide a definition. Hence, there is no confusion.
3. Examples
In this section, I will provide examples of interfaces and abstract classes.
3.1. Interface
MobilePhone
interface defines the contract of any type of mobile phones in the example,
/** * @author Santosh Balgar Sachchidananda * MobileInterface defines the contract which all types of mobile phones * in the example have to adhere to */ public interface MobilePhone { void makeACall(Long number, Integer countryCode); boolean sendSMS(String message); }
BasicMobilePhone
class implements the MobilePhone
interface. It has to provide definition for all the methods in MobilePhone
interface. Otherwise, implementing class has to be declared as abstract.
/** * author Santosh Balgar Sachchidananda * BasicMobilePhone implements MobilePhone interface and provide definition for all the methods. * It also has additional method apart from the interface contract */ class BasicMobilePhone implements MobilePhone { /** * @param number * @param countryCode * Overridden from MobilePhone interface */ @Override public void makeACall(Long number, Integer countryCode) { System.out.println(String.format("I can call to number %d-%d", countryCode, number)); } /* * @param message * @return * Overriden from MobilePhone interface */ @Override public boolean sendSMS(String message) { System.out.println("I can send SMS"); return true; } /** * Own method */ public void supportClassicGames() { System.out.println("I can support classic games"); } }
SmartPhone
is the another class adhering to the MobilePhone
contract.
/** * @author Santosh Balgar Sachchidananda * SmartPhone class implements MobilePhone interface. It has to provide definition for all the methods. * Also it has additional methods. */ class SmartPhone implements MobilePhone { /** * @param number * @param countryCode * Overridden from MobilePhone interface */ @Override public void makeACall(Long number, Integer countryCode) { System.out.println(String.format("I can make audio and video call to %d-%d", countryCode, number)); } /** * @param message * @return * Overridden from MobilePhone interface */ @Override public boolean sendSMS(String message) { System.out.println("I can send SMS"); return true; } /** * own method of SmartPhone class */ public void canCapturePhoto() { System.out.println("I can take HD photo"); } }
InterfaceDemo
is the driver class which can be invoked to run the example.
/** * author Santosh Balgar Sachchidananda * InterfaceDemo is the driver class for interfaces */ public class InterfaceDemo { public static void main(String[] args) { MobilePhone basicMobilePhone = new BasicMobilePhone(); MobilePhone smartPhone = new SmartPhone(); System.out.println("Basic Mobile Phone features"); basicMobilePhone.makeACall(1234567890L, 91); basicMobilePhone.sendSMS("Hello world!!!"); ((BasicMobilePhone) basicMobilePhone).supportClassicGames(); System.out.println("-------------------------------------------------"); System.out.println("Smart Phone features"); smartPhone.makeACall(1234567890L, 91); smartPhone.sendSMS("Hello world!!!"); ((SmartPhone) smartPhone).canCapturePhoto(); } }
Below is the output of InterfaceDemo
,
When there is a need to inherit from multiple interfaces then use the syntax similar to public class ClassA implements Interface1, Interface2
. ClassA should provide definition to the methods from both Interface1
and Interface2
.
3.2. Abstract Class
AndroidPhone
is an abstract class that adheres to the MobilePhone
interface. AndroidPhone
will have to exhibit certain behaviors and all other classes extending from it have to adhere to it.
import com.jcg.java7.interfaces.MobilePhone; import com.jcg.java7.interfaces.MobilePhone; /** * @author Santosh Balgar Sachchidananda * AndroidPhone is an abstract class. This defines the construct for any android phone in the example. * Basic phone contract is implemented from MobilePhone interface. However the definitions of those * methods have to be provided in the class extended from the AndroidPhone */ abstract class AndroidPhone implements MobilePhone { /** * Concrete method in the abstract class */ public final void displayPhoneOSType() { System.out.println("I run on Android OS"); } /** * An abstract method. Inheriting class should provide the definition */ public abstract void capturePhoto(); }
BrandAPhone
is of AndroidPhone
type and provides a definition of abstract method.
import com.sun.deploy.util.StringUtils; import com.sun.deploy.util.StringUtils; /** * @author Santosh Balgar Sachchidananda * BrandAPhone is a Android type phone. It extends AndroidPhone bstract class */ class BrandAPhone extends AndroidPhone{ @Override //Overridden from AndroidPhone abstract class public void capturePhoto() { System.out.println("BrandAPhone can capture photo"); } @Override //Method contract from the MobilePhone interface public void makeACall(Long number, Integer countryCode) { System.out.println(String.format("BrandAPhone can make audio and video calls to 0%d-%d", countryCode, number)); } @Override //Method contract from MobilePhone interface public boolean sendSMS(String message) { System.out.println(String.format("BrandAPhone can send text message - %s", message)); return true; } }
BrandAPhoneDemo
is the driver class to run the abstract class demo.
/** * @author Santosh Balgar Sachchidananda * This is the driver program to demonstrate the abstract class */ public class BrandAPhoneDemo { public static void main(String[] args) { System.out.println("This class demonstrates the use of abstract class in Java"); System.out.println("----------------------------------------------------------"); AndroidPhone brandAPhone = new BrandAPhone(); //Final method inherited from AndroidPhone abstract class brandAPhone.displayPhoneOSType(); brandAPhone.makeACall(1234567890L, 91); brandAPhone.sendSMS("Hello, world!!!!"); brandAPhone.capturePhoto(); System.out.println("----------------------------------------------------------"); } }
The output from BrandAPhoneDemo
is as below,
4. Java 8 interface enhancements
Java 8 tried to solve some of the design concerns around the interfaces, if not designed correctly interfaces lead to the constant change of classes.
4.1. The change
Prior to java 8, interfaces are designed to define a contract. They had only abstract methods and final constants. With Java 8 interfaces have got a facelift. Now interfaces can have default and static methods (definitions). Default methods can be overridden. Whereas, static methods can’t be overridden. All the classes implementing interface should provide definition of all the methods in the interface. For some reason, if the designers had to change the interface, then all the implementing classes are affected. They all have to provide a definition for the new method. Java 8’s interface default and static methods provide a way to overcome this problem.
4.2. Java 8 interface example
Below interface, MobileInterface
is an example demoing the Java 8 interface enhancements
/** * @author: Santosh Balgar Sachchiananda * This example shows the Java8 interface default methods */ public interface MobileInterface { /** * Java8 adds capability to have static method in interface. * Static method in interface Can't be overridden */ public static void printWelcomeMessage() { System.out.println("***STATIC METHOD*** Welcome!!"); } /* * Java8 adds capability of providing a default definition of method in an interface. * Default method can be overridden by the implementing class */ default void makeACall(Long number) { System.out.println(String.format("***DEFAULT METHOD*** Calling ...... %d", number)); } /* * Regular interface method, which every class needs to provide a definition */ public void capturePhoto(); }
Class MobileInterfaceDemo
is the driver program. BasicPhone
and SmartPhone
classes implement the interface MobileInterface
and override the methods from MobileInterface
.
BasicPhone
overrides only the mandatory abstract methodcapturePhoto()
SmartPhone
class overrides default methodmakeACall()
and the mandatory abstract methodcapturePhoto()
/** * BasicMobile class provides definition only for mandatory abstract method * Need to provide definition for capturePhoto() * Whereas, makeACall() takes the default implementation */ class BasicPhone implements MobileInterface { @Override public void capturePhoto() { System.out.println("***BASIC PHONE*** Cannot capture photo"); } } /** * SmartPhone class overrides both default method and abstract method * Provides definition for both makeACall() and capturePhoto() methods */ class SmartPhone implements MobileInterface { @Override public void makeACall(Long number) { System.out.println(String.format("***SMART PHONE*** Can make voice and video call to number .... %d", number)); } @Override public void capturePhoto() { System.out.println("***SMART PHONE*** Can capture photo"); } } /** * MobileInterfaceDemo is the driver class */ public class MobileInterfaceDemo { public static void main(String[] args) { MobileInterface basicPhone = new BasicPhone(); MobileInterface smartPhone = new SmartPhone(); // Calls static method of interface MobileInterface.printWelcomeMessage(); System.out.println("********************** BASIC PHONE ************************"); // Calls default implementation of interface basicPhone.makeACall(1234567890L); // Calls abstract method of interface basicPhone.capturePhoto(); System.out.println("********************** SMART PHONE ************************"); // Calls overridden implementation of makeACall() smartPhone.makeACall(1234567890L); // Calls abstract method of interface smartPhone.capturePhoto(); } }
The output from the MobileInterfaceDemo
,
5. Guidelines to use interfaces and abstract classes
In real-world project projects if you are defining a contract which you want all the implementing classes to adhere to, then go for an interface. Interfaces are the best way to define the contract and concrete class can extend behaviors from another contract class. A classic example is Java threads.
If the use-case is to design a dynamic application whose features are to be extended in the near future and the requirement is to exhibit some concrete behavior then go for an abstract class. The caveat is, the concrete class cannot inherit behavior by extending any other class.
6. Instructions to run the code
Code download link is provided in the download section. Code has been written using IntelliJ Idea IDE. Unzip the attached code an import it as a Java project in IntelliJ. Choose the class with the main method (InterfaceDemo
, BrandAPhoneDemo
), right-click and run.
7. Download the Source Code
You can download the full source code of this example here: Interface vs Abstract Class Java Example