Differences between Java Interfaces and Abstract Classes: When to Use Interfaces and When to Use Abstract Classes

In Java, there are two very important concepts—abstract classes and interfaces. Both help design more flexible and clear code structures, but many beginners often confuse them or even don’t know when to use each. Today, we’ll explore their differences in detail and their respective applicable scenarios.

1. Different Definition Methods

The declaration methods of abstract classes and interfaces are distinct:
- Abstract Class: Declared using abstract class. For example:

  abstract class Animal { // Abstract class
      // Can have abstract methods and concrete methods
      public abstract void makeSound(); // Abstract method (no body)
      public void breathe() { // Concrete method (has a body)
          System.out.println("Animals breathe");
      }
  }
  • Interface: Declared using interface. For example:
  interface Flyable { // Interface
      void fly(); // By default: public abstract (before JDK 8)
  }

2. Different Inheritance/Implementation Relationships

  • Abstract Class: A class inherits from an abstract class using extends (Java uses single inheritance; a class can only extend one abstract class).
  • Interface: A class implements an interface using implements (a class can implement multiple interfaces, achieving multi-inheritance effects); interfaces can also inherit from other interfaces using extends.

3. Differences Between Methods and Member Variables

Methods

  • Abstract Class: Can contain abstract methods (abstract, no body) and concrete methods (with a body). If a class contains abstract methods, it must be abstract.
  • Interface: Before JDK 8, all methods were implicitly public abstract (must be implemented). From JDK 8+, default methods (default, with a body) and static methods (static, with a body) are added. For example:
  interface Printable {
      default void print() { // Default method: all implementing classes can use directly
          System.out.println("Default print behavior");
      }
      static void staticMethod() { // Static method (has a body)
          System.out.println("Static method");
      }
  }

Member Variables

  • Abstract Class: Can have member variables with various modifiers (instance variables, class variables). For example:
  abstract class Animal {
      private String name; // Instance variable
      public static int count = 0; // Class variable (static variable)
  }
  • Interface: Only allows member variables modified by public static final (i.e., constants, unmodifiable). For example:
  interface Constants {
      int MAX_SIZE = 100; // Constant (implicitly public static final)
  }

4. Constructors

  • Abstract Class: Can have constructors, which are called during initialization of subclasses (abstract classes cannot be instantiated directly, but subclasses use super to call the parent class constructor).
  • Interface: Has no constructors (since interfaces cannot be instantiated and do not require initialization).

5. Different Design Purposes

Abstract Class: Emphasizes “What It Is” (Inheritance)

An abstract class acts as a “template” to describe the common characteristics of a class of things. For example:
- Define an Animal abstract class with a concrete method breathe() (all animals breathe) and an abstract method makeSound() (specific sounds vary by subclass).
- Subclasses like Dog and Cat inherit from Animal, reuse breathe(), and only need to implement makeSound().

Interface: Emphasizes “What It Can Do” (Implementation)

An interface acts as a “capability list” to describe the behaviors a class of things can perform. For example:
- Define a Flyable interface that specifies the method fly(), without caring about “who is flying”.
- Different classes (e.g., Bird, Airplane) can implement Flyable, each with its own fly() method (birds fly by flapping wings; airplanes fly via engines).

When to Use an Abstract Class?

  1. Need to Share Code: Abstract classes provide reusable methods and variables, reducing duplication. For example: breathe() in Animal.
  2. Strong “Is-A” Relationship: Subclasses and the parent class have an “is-a” relationship. For example: Cat is a subclass of Animal—abstract classes are more appropriate here.
  3. Partial Implementation + Partial Abstraction: Abstract classes can include concrete methods, so subclasses only need to implement abstract methods. For example: A Shape abstract class has a concrete area calculation method, and subclasses like Circle only need to implement getRadius().

When to Use an Interface?

  1. Multi-Implementation Scenarios: A class needs to implement multiple independent behaviors (Java allows single inheritance but multiple interface implementations). For example: A Duck class can implement both Flyable and Swimmable interfaces.
  2. Define Behavioral Specifications: Interfaces only specify “what to do”, not “how to do it”. For example: Define a Printable interface; any class implementing it must have a print() method (implementation details are left to the class).
  3. Shared Behaviors Without Inheritance: Different classes have no “is-a” relationship but share common behaviors. For example: Bird and Airplane can both fly, so they implement the Flyable interface.

Summary

  • Abstract Class: A “template” that provides partial implementations, for sharing code among classes with inheritance relationships, emphasizing “what it is”.
  • Interface: A “contract” that specifies rules, for multi-implementation scenarios or defining behavioral specifications, emphasizing “what it can do”.

If unsure, remember: Choose an abstract class when code sharing via inheritance is needed; choose an interface when multi-implementation or behavioral specifications are required.

Xiaoye