Java

Compare Abstract Classes and Interfaces in Java and When to Use Each

By Utility Zone · 2025-11-06T10:13:38.609518

Both abstract classes and interfaces are mechanisms for achieving abstraction in Java, but they serve different purposes and are used in different scenarios. Understanding when to use each is crucial for designing well-structured, maintainable applications.12

Comparison between Abstract Classes and Interfaces in Java showing syntax, features, and use cases

Comparison between Abstract Classes and Interfaces in Java showing syntax, features, and use cases


What is an Abstract Class?

An abstract class is a class declared with the abstract keyword that cannot be instantiated directly (you cannot create objects from it). It serves as a blueprint for subclasses and can contain both abstract methods (methods without implementation) and concrete methods (methods with implementation).134

Key Characteristics of Abstract Classes:341

  • Cannot be instantiated: You cannot create objects directly; must be extended by subclasses34
  • Mix of abstract and concrete methods: Can have both abstract methods (without body) and regular methods (with implementation)13
  • Constructors: Can have constructors to initialize variables when subclasses are instantiated13
  • Access modifiers: Can have any access modifier (public, protected, private)51
  • Member variables: Can have final, non-final, static, and non-static variables51
  • Single inheritance: A class can extend only one abstract class21
  • Keyword: Declared using the abstract keyword and extended using extends31

Abstract Class Syntax

abstract class ClassName {
    // Abstract method (no body)
    abstract void abstractMethod();
    
    // Concrete method (with body)
    void concreteMethod() {
        System.out.println("This method has implementation");
    }
}

Abstract Class Example

// Abstract class (parent)
abstract class Animal {
    // Concrete method - shared by all animals
    public void sleep() {
        System.out.println("Animal is sleeping");
    }
    
    // Abstract method - to be implemented by subclasses
    abstract void makeSound();
    
    // Constructor
    Animal() {
        System.out.println("Animal object created");
    }
}

// Concrete class (child)
class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Dog barks: Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        // Animal a = new Animal();  // Error: Cannot instantiate abstract class
        
        Dog dog = new Dog();
        dog.makeSound();  // Output: Dog barks: Woof!
        dog.sleep();      // Output: Animal is sleeping
    }
}

Output:

Animal object created
Dog barks: Woof!
Animal is sleeping

What is an Interface?

An interface is a completely abstract type that defines a contract (a set of abstract methods) that implementing classes must follow. Before Java 8, interfaces could only contain abstract methods, but since Java 8, they can also have default and static methods.678910

Key Characteristics of Interfaces:176

  • Cannot be instantiated: Like abstract classes, interfaces cannot create objects6
  • Abstract methods by default: All methods are abstract unless declared as default or static76
  • No constructors: Cannot have constructors17
  • All public members: All methods and variables are implicitly public517
  • Constants only: Variables are implicitly public, static, and final (constants)17
  • Multiple inheritance: A class can implement multiple interfaces21
  • Keyword: Declared using the interface keyword and implemented using implements61
  • Java 8+: Can have default methods (with implementation) and static methods89

Interface Syntax

interface InterfaceName {
    // Constants
    int CONSTANT = 10;
    
    // Abstract methods
    void abstractMethod();
    
    // Default method (Java 8+)
    default void defaultMethod() {
        System.out.println("Default implementation");
    }
    
    // Static method (Java 8+)
    static void staticMethod() {
        System.out.println("Static method");
    }
}

Interface Example

// Interface
interface Drivable {
    void accelerate();
    void brake();
    
    // Default method (Java 8+)
    default void honk() {
        System.out.println("Honk! Honk!");
    }
}

// Implementing class
class Car implements Drivable {
    @Override
    public void accelerate() {
        System.out.println("Car is accelerating");
    }
    
    @Override
    public void brake() {
        System.out.println("Car is braking");
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.accelerate();  // Output: Car is accelerating
        car.brake();       // Output: Car is braking
        car.honk();        // Output: Honk! Honk! (default method)
    }
}

Output:

Car is accelerating
Car is braking
Honk! Honk!

Multiple Interface Implementation

A class can implement multiple interfaces, which allows it to inherit the method contracts from multiple sources:1112

interface Drivable {
    void drive();
}

interface Flyable {
    void fly();
}

// Class implements multiple interfaces
class AmphibiousCraft implements Drivable, Flyable {
    @Override
    public void drive() {
        System.out.println("Driving on road");
    }
    
    @Override
    public void fly() {
        System.out.println("Flying in air");
    }
}

public class Main {
    public static void main(String[] args) {
        AmphibiousCraft craft = new AmphibiousCraft();
        craft.drive();  // Output: Driving on road
        craft.fly();    // Output: Flying in air
    }
}

Output:

Driving on road
Flying in air

Side-by-Side Comparison

FeatureAbstract ClassInterface
Declarationabstract classinterface
InstantiationCannot instantiateCannot instantiate
Inheritanceextends (single)implements (multiple)
Multiple InheritanceNot supportedSupported
MethodsConcrete + abstractAbstract only (+ default/static since Java 8)
ConstructorsCan have constructorsNo constructors
Access ModifiersAny (public, private, protected)Only public (implicit)
VariablesAny type (final, non-final, static, non-static)Only constants (public static final)
Method ImplementationCan be mixedMethods must have implementation (default/static) or be abstract
Abstraction LevelPartial abstraction (0-100%)Complete abstraction (100%)25
Use CaseShared code among related classesDefine contract/behavior for unrelated classes

When to Use Abstract Classes

Use abstract classes when:1314

  1. Shared Implementation: You want to share code and state (variables) among related classes114
    • Abstract classes allow you to provide common, implemented functionality for all implementations
  2. Control Access: You need protected or private members that aren't accessible from outside141
    • Interfaces force everything to be public
  3. Non-Static/Non-Final Variables: You need instance variables or mutable state21
    • Interfaces can only have constants
  4. Forward Compatibility: You anticipate adding new methods in the future114
    • You can add new concrete methods to an abstract class without breaking existing implementations
  5. Constructor Logic: You need to initialize objects with specific logic51
    • Interfaces cannot have constructors
  6. Versioning: You want to create multiple versions of your component141

Example: Best Used with Abstract Class

// Vehicle hierarchy - classes share common behavior
abstract class Vehicle {
    // Shared implementation
    private String model;
    private int year;
    
    // Constructor
    Vehicle(String model, int year) {
        this.model = model;
        this.year = year;
    }
    
    // Concrete method - shared by all vehicles
    public void displayInfo() {
        System.out.println("Model: " + model + ", Year: " + year);
    }
    
    // Abstract method - specific to each vehicle
    abstract void startEngine();
}

class Car extends Vehicle {
    Car(String model, int year) {
        super(model, year);
    }
    
    @Override
    void startEngine() {
        System.out.println("Car engine started");
    }
}

class Truck extends Vehicle {
    Truck(String model, int year) {
        super(model, year);
    }
    
    @Override
    void startEngine() {
        System.out.println("Truck diesel engine started");
    }
}

When to Use Interfaces

Use interfaces when:1314

  1. Unrelated Classes: Multiple unrelated classes should implement the same behavior114
    • Classes don't need to share a common parent
  2. Multiple Contracts: A class needs to inherit from multiple sources21
    • Implement multiple interfaces to satisfy multiple contracts
  3. Pure Contract: You're defining a contract without implementation details141
    • Interfaces specify "what" should be done, not "how"
  4. Capability: You're defining a capability or role that diverse classes can play13
    • Example: Serializable, Comparable, Runnable
  5. API Design: You're designing a public API114
    • Interfaces provide flexibility for future implementations
  6. Framework Requirement: Working with frameworks that require interface-based design (Spring, Java Collections Framework)14

Example: Best Used with Interface

// Different entities implementing the same behavior
interface Drawable {
    void draw();
}

interface Resizable {
    void resize(double factor);
}

class Circle implements Drawable, Resizable {
    private double radius;
    
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
    
    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius: " + radius);
    }
}

class Rectangle implements Drawable, Resizable {
    private double width, height;
    
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
    
    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized");
    }
}

Default Methods in Interfaces (Java 8+)

Starting from Java 8, interfaces can have default methods with implementations. This bridges the gap between interfaces and abstract classes:8910

Syntax:98

interface InterfaceName {
    default void defaultMethod() {
        // Default implementation
    }
}

Benefits:1089

  • Backward Compatibility: Add new methods to existing interfaces without breaking implementing classes810
  • API Evolution: Extend interfaces gracefully108
  • Lambda Support: Enable functional programming features8

Example:98

interface Animal {
    // Abstract method
    void makeSound();
    
    // Default method (Java 8+)
    default void sleep() {
        System.out.println("Animal is sleeping");
    }
}

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
    // Dog inherits the sleep() method - no need to implement
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.makeSound();  // Output: Woof!
        dog.sleep();      // Output: Animal is sleeping (default)
    }
}

Output:

Woof!
Animal is sleeping

Practical Decision Tree

When choosing between abstract class and interface, consider:1314

  1. Do the classes share a common parent concept?
    • YES → Abstract class
    • NO → Interface
  2. Do you need to share code/state?
    • YES → Abstract class
    • NO → Interface
  3. Do multiple unrelated classes need the same behavior?
    • YES → Interface
    • NO → Abstract class
  4. Do you need non-public members?
    • YES → Abstract class
    • NO → Interface
  5. Should this class have multiple supertypes?
    • YES → Interface
    • NO → Abstract class

Real-World Example: Combined Usage

// Interface defines the contract
interface PaymentProcessor {
    void processPayment(double amount);
    default void logTransaction() {
        System.out.println("Transaction logged");
    }
}

// Abstract class provides shared implementation
abstract class BasePaymentProcessor implements PaymentProcessor {
    protected double balance;
    protected String accountNumber;
    
    BasePaymentProcessor(String accountNumber, double balance) {
        this.accountNumber = accountNumber;
        this.balance = balance;
    }
    
    // Concrete method - shared
    public void displayBalance() {
        System.out.println("Balance: " + balance);
    }
    
    // Abstract method - specific to each processor
    abstract void validatePayment(double amount);
}

// Concrete class
class CreditCardProcessor extends BasePaymentProcessor {
    CreditCardProcessor(String accountNumber, double limit) {
        super(accountNumber, limit);
    }
    
    @Override
    void validatePayment(double amount) {
        if (amount <= balance) {
            System.out.println("Payment validated");
        }
    }
    
    @Override
    public void processPayment(double amount) {
        validatePayment(amount);
        balance -= amount;
        logTransaction();
    }
}

Understanding the distinction between abstract classes and interfaces, and knowing when to use each, is essential for writing clean, object-oriented Java code. The choice between them shapes the architecture and maintainability of your application.1213 <span style="display:none">15161718</span>


<div align="center">⁂</div>

Footnotes

  1. https://www.geeksforgeeks.org/java/difference-between-abstract-class-and-interface-in-java/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19 ↩20 ↩21 ↩22 ↩23 ↩24 ↩25 ↩26

  2. https://www.shiksha.com/online-courses/articles/difference-between-abstract-class-and-interface/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  3. https://www.datacamp.com/doc/java/abstract ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  4. https://www.programiz.com/java-programming/abstract-classes-methods ↩ ↩2 ↩3

  5. https://www.simplilearn.com/abstract-class-vs-interface-java-article ↩ ↩2 ↩3 ↩4 ↩5

  6. https://www.programiz.com/java-programming/interfaces ↩ ↩2 ↩3 ↩4 ↩5

  7. https://dev.java/learn/interfaces/defining-interfaces/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  8. https://www.geeksforgeeks.org/java/default-methods-java/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9

  9. https://www.tutorialspoint.com/java/java_default_methods.htm ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  10. https://www.educative.io/courses/java-8-lambdas-stream-api-beyond/default-methods-in-interfaces ↩ ↩2 ↩3 ↩4 ↩5

  11. https://www.w3schools.com/java/java_interface.asp ↩

  12. https://www.w3schools.com/java/ref_keyword_implements.asp ↩

  13. https://codefinity.com/blog/Interface-vs-Abstract-Class ↩ ↩2 ↩3 ↩4 ↩5

  14. https://www.tutorialspoint.com/when-to-use-an-abstract-class-and-when-to-use-an-interface-in-java ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11

  15. https://www.geeksforgeeks.org/java/abstract-methods-in-java-with-examples/ ↩

  16. https://www.geekster.in/articles/interfaces-in-java/ ↩

  17. https://www.scaler.com/topics/abstract-method-in-java/ ↩

  18. https://www.digitalocean.com/community/tutorials/java-8-interface-changes-static-method-default-method ↩