In the previous articles, we learned what interfaces are, how they work, and why they are fundamental to Java programming.
However, one question still remains:
When should we use an Interface, an Abstract Class, or a Concrete Class?
This is one of the most frequently asked Java interview questions because choosing the right abstraction directly affects the design, flexibility, and maintainability of your application.
In this article, we'll compare these three concepts in depth with practical examples and interview-oriented explanations.
Why Do We Need Different Types of Classes?
Not every Java class serves the same purpose.
Sometimes, you only know what should be done but not how.
Sometimes, you already have some common implementation.
Sometimes, everything is fully implemented and ready to use.
Java provides three different constructs for these situations:
- Interface
- Abstract Class
- Concrete Class
Choosing the right one helps build clean, reusable, and maintainable software.
When Should You Use an Interface?
Use an interface when you only know the requirement or contract, but not the implementation.
In other words, an interface defines what a class should do, not how it should do it.
Example:
interface PaymentService {
void processPayment();
}
The interface does not care whether the payment is processed using:
- Credit Card
- UPI
- Net Banking
- PayPal
Each implementation class decides that.
Step-by-Step Explanation
Step 1
The interface defines the required service.
Step 2
No implementation is provided.
Step 3
Implementation classes decide how to perform the task.
Step 4
Clients use the interface without depending on a specific implementation.
When Should You Use an Abstract Class?
Use an abstract class when you already know part of the implementation, but some behavior still depends on child classes.
Example:
abstract class PaymentService {
public void validatePayment() {
System.out.println("Validating payment...");
}
public abstract void processPayment();
}
Here:
- Validation logic is common.
- Payment processing differs for each payment type.
Step-by-Step Explanation
Step 1
The abstract class provides common code.
Step 2
Some methods remain abstract.
Step 3
Child classes inherit common functionality.
Step 4
Each child implements only the missing behavior.
When Should You Use a Concrete Class?
Use a concrete class when everything is fully implemented and ready for use.
Example:
class CreditCardPaymentService {
public void processPayment() {
System.out.println("Payment completed.");
}
}
The class is complete.
Objects can be created immediately.
Quick Decision Table
| Situation | Use |
|---|---|
| Only requirement specification | Interface |
| Partial implementation | Abstract Class |
| Complete implementation | Concrete Class |
Interface vs Abstract Class
Let's compare them feature by feature.
1. Purpose
| Interface | Abstract Class |
|---|---|
| Defines a contract | Provides partial implementation |
2. Methods
Traditionally, interface methods are abstract.
interface PaymentService {
void processPayment();
}
Abstract classes may contain both abstract and concrete methods.
abstract class PaymentService {
abstract void processPayment();
void validatePayment() {
}
}
Modern Java Note: Since Java 8, interfaces can also contain
defaultandstaticmethods, and since Java 9,privatehelper methods. This article focuses on the traditional interview concepts while acknowledging these modern additions.
3. Variables
Interface variables are always constants.
interface AppConstants {
int MAX_USERS = 100;
}
The compiler treats it as:
public static final int MAX_USERS = 100;
Abstract classes can contain:
- Instance variables
- Static variables
- Final variables
Example:
abstract class Employee {
protected String employeeName;
protected int employeeId;
}
4. Constructors
Interfaces do not define constructors because they are not instantiated.
Abstract classes can define constructors.
Example:
abstract class Employee {
Employee() {
System.out.println("Employee initialized.");
}
}
When a child object is created, the abstract class constructor executes automatically.
5. Initialization Blocks
Interfaces cannot contain:
- Instance initialization blocks
Abstract classes can.
Example:
abstract class Employee {
{
System.out.println("Instance block");
}
}
6. Object Creation
Interfaces:
PaymentService service = new PaymentService();
Compile-Time Error
PaymentService is abstract; cannot be instantiated
Abstract classes:
abstract class PaymentService {
}
PaymentService service = new PaymentService();
Compile-Time Error
PaymentService is abstract; cannot be instantiated
Concrete classes:
class CreditCardPaymentService {
}
CreditCardPaymentService service =
new CreditCardPaymentService();
Works successfully.
Complete Comparison Table
| Feature | Interface | Abstract Class | Concrete Class |
|---|---|---|---|
| Object Creation | ❌ No | ❌ No | ✅ Yes |
| Constructors | ❌ No | ✅ Yes | ✅ Yes |
| Instance Variables | ❌ No | ✅ Yes | ✅ Yes |
| Static Variables | ✅ Yes | ✅ Yes | ✅ Yes |
| Abstract Methods | ✅ Yes | ✅ Yes | ❌ No |
| Concrete Methods | ✅ Yes (default/static methods in modern Java) | ✅ Yes | ✅ Yes |
| Multiple Inheritance | ✅ Supported | ❌ Not Supported | ❌ Not Supported |
| Primary Purpose | Contract | Partial implementation | Complete implementation |
Real-World Example
Suppose you're building an online shopping application.
Interface
interface PaymentService {
void processPayment();
}
Abstract Class
abstract class BasePaymentService
implements PaymentService {
public void validate() {
System.out.println("Validation completed.");
}
}
Concrete Class
class CreditCardPaymentService
extends BasePaymentService {
@Override
public void processPayment() {
System.out.println("Credit Card Payment.");
}
}
ASCII Diagram
PaymentService
(Interface)
│
▼
BasePaymentService
(Abstract Class)
│
▼
CreditCardPaymentService
(Concrete Class)
Common Beginner Mistakes
Mistake 1: Using an Abstract Class When Only a Contract Is Needed
If there is no shared implementation, prefer an interface.
Mistake 2: Putting Business Logic Inside an Interface
Interfaces should define contracts.
Complex implementation belongs in classes.
Mistake 3: Making Every Class Abstract
Only use an abstract class when you genuinely want to prevent direct instantiation and share common implementation.
Mistake 4: Forgetting That Abstract Classes Can Have Constructors
Many beginners incorrectly assume abstract classes cannot have constructors.
They absolutely can.
Best Practices
- Prefer interfaces when multiple implementations are expected.
- Use abstract classes for shared code and common state.
- Keep concrete classes focused on business logic.
- Design around interfaces to reduce coupling.
- Follow the SOLID principles, especially the Dependency Inversion Principle (DIP).
Interview Questions
1. When should you use an interface?
When only the contract is known and multiple implementations are expected.
Why interviewers ask
To evaluate your understanding of abstraction and API design.
2. When should you use an abstract class?
When multiple classes share common state or behavior, but some methods still require implementation by subclasses.
3. Can an abstract class have a constructor?
Yes.
It is executed whenever a child class object is created.
4. Can we create an object of an interface?
No.
Interfaces cannot be instantiated.
5. Can we create an object of an abstract class?
No.
Only its subclasses can be instantiated.
6. Why can interfaces support multiple inheritance but classes cannot?
Interfaces primarily define contracts, avoiding the ambiguity caused by inheriting multiple implementations.
7. Which is better: Interface or Abstract Class?
Neither is universally better.
Choose based on the problem:
- Interface → Contract and flexibility
- Abstract Class → Shared implementation
- Concrete Class → Complete implementation
Common trap
Saying "always use interfaces" or "abstract classes are outdated." The correct choice depends on your design requirements.
Quick Memory Trick 🧠
Remember IPC:
Interface
│
▼
Requirement (Contract)
Abstract Class
│
▼
Partial Implementation
Concrete Class
│
▼
Complete Implementation
Think IPC whenever you need to decide which one to use.
Key Takeaways
- Use an interface when defining a contract.
- Use an abstract class for partial implementation and shared state.
- Use a concrete class when the implementation is complete.
- Interfaces focus on what should be done.
- Abstract classes combine what and how.
- Concrete classes provide the final implementation.
- Abstract classes can have constructors and instance variables.
- Interfaces enable multiple inheritance of type, while classes do not support multiple inheritance.
If you found this guide helpful, leave a ❤️ and follow for more beginner-friendly Java tutorials, interview questions, and practical coding examples.
Happy Coding!
Top comments (0)