Abstraction
Interface vs Abstract Class
Conduct a comprehensive comparative analysis of capabilities, design heuristics, and dynamic dispatch table lookups.
Interview: Highly tested: multiple inheritance differences, state support (instance variables), when to use which, and dynamic dispatch performance (vtable vs itable).
Choosing between an Abstract Class and an Interface is a key design decision. While abstract classes represent identity (IS-A) and support shared state, interfaces represent capability (HAS-A) and support multiple inheritance of behavior.
State vs. Capability
Abstract classes hold instance variables (state). Interfaces can only hold public static constants (no instance state).
Inheritance Model
Classes are limited to single inheritance. Classes can implement any number of interfaces.
vtable vs. itable
Class method calls (vtable) run with constant-offset indexing. Interface methods (itable) require dynamic searches, adding slight overhead.
Structural Comparisons
The choice between interfaces and abstract classes depends on structural and architectural needs:
| Feature | Abstract Class | Interface |
|---|---|---|
| Multiple Inheritance | No. Classes can extend only one class. | Yes. Classes can implement multiple interfaces. |
| Instance Variables | Yes. Can declare private/protected instance fields. | No. Fields are implicitly public static final. |
| Constructors | Yes. Used to initialize state during subclassing. | No. Interfaces cannot have constructors. |
| Access Modifiers | Can declare private, protected, or public members. | Methods are public (except private helpers since Java 9). |
JVM Method Dispatch: vtable vs. itable
The JVM resolves class methods and interface methods differently at runtime:
- vtable (Virtual Method Table): Used for class-based calls. Because Java supports only single class inheritance, the layout of the vtable is predictable. A method declared at index 3 in a superclass always occupies index 3 in all subclasses. This allows fast, constant-offset array indexing.
- itable (Interface Method Table): Used for interface-based calls. Because a class can implement multiple interfaces in different orders, the JVM cannot guarantee constant offsets. Calling an interface method requires a search-based lookup within the class's itable mapping, adding a slight performance overhead compared to vtable access.
Common Pitfalls
- Using Abstract Classes for Shared Behavior: Restricting subclasses to a single inheritance path when the shared behavior is simple and could be declared in an interface.
- Poluting Interfaces with Constants: Declaring constant variables in interfaces and implementing the interface to access them, violating clean design guidelines.
Best Practices
- Use Abstract Classes for Template Models (IS-A): Choose abstract classes when modeling close relationships that share state and implementation logic.
- Use Interfaces for Decoupled Capabilities (HAS-A): Choose interfaces to define common capabilities (e.g.
Flyable) that are shared across unrelated class hierarchies.
Interview-Relevant Information
Q1: When should you use an abstract class instead of an interface?
Answer: Use an abstract class when you need to define a common identity (IS-A) and share state (instance fields) or constructors among closely related classes. Use an interface to define polymorphic capabilities (HAS-A) that can be implemented by completely unrelated classes.
Q2: Why are interface method lookups (itable) slightly slower than class method lookups (vtable) in the JVM?
Answer: Class dispatch (vtable) uses a predictable single-inheritance layout where methods reside at fixed array offsets. Interface dispatch (itable) must resolve multiple inheritance, requiring the JVM to look up and resolve mapping offsets dynamically, which introduces a search-based overhead.
Quick Checklist
Can you compare the capabilities of abstract classes and interfaces, select the correct structure based on design constraints, and explain the performance trade-offs of vtable vs itable dispatch? If yes, you understand the difference.
Use Cases
Designing plugins that inherit base contexts (abstract class) and register lifecycle hooks (interfaces).
Building clean domain frameworks using interfaces to expose APIs and abstract classes to manage state.
Common Mistakes
Over-relying on abstract classes and locking client code into rigid single-inheritance trees.
Poluting public interfaces with internal constants to simplify imports, violating encapsulations.