Abstract Classes
An abstract class in Java is a partially implemented class that provides abstraction by defining what a class should do, while allowing subclasses to decide how to do it. It is used when classes share common behavior but must implement specific details differently. This is a high-frequency interview topic, often compared with interfaces.
What Is an Abstract Class?
- Declared using the abstract keyword
- Can contain abstract methods (no body)
- Can contain concrete methods (with body)
- Cannot be instantiated
- Supports inheritance-based abstraction
abstract class Vehicle {
abstract void start();
}
Why Abstract Classes Are Needed
- Avoid code duplication
- Share common functionality
- Enforce method implementation in subclasses
- Provide partial abstraction
- Improve design consistency
Abstract Method
An abstract method has no implementation and must be implemented by subclasses.
abstract void start();
- ✔ Ends with semicolon
- ✔ No method body
Abstract Class Example (Basic)
abstract class Vehicle {
abstract void start(); // abstract method
void fuel() { // concrete method
System.out.println("Fueling vehicle");
}
}
class Car extends Vehicle {
@Override
void start() {
System.out.println("Car starts with key");
}
}
Vehicle v = new Car();
v.start();
v.fuel();
✔ Abstraction + polymorphism
Key Rules of Abstract Classes (Very Important)
- Cannot create an object of an abstract class
// Vehicle v = new Vehicle(); // ❌
- Can have abstract and non-abstract methods
- Can have constructors
abstract class A {
A() {
System.out.println("Constructor");
}
}
- Can have instance variables
- Can extend only one class
- A subclass must implement all abstract methods (unless the subclass is also abstract)
Abstract Class with Constructor
abstract class Shape {
Shape() {
System.out.println("Shape created");
}
abstract double area();
}
class Circle extends Shape {
double radius;
Circle(double r) {
radius = r;
}
double area() {
return 3.14 * radius * radius;
}
}
✔ Constructors run from parent to child
Abstract Class with Partial Implementation
abstract class Bank {
abstract double getRateOfInterest();
double calculateInterest(double amount) {
return amount * getRateOfInterest() / 100;
}
}
✔ Common logic reused
✔ Rate differs per bank
Abstract Class vs Concrete Class
| Feature | Abstract Class | Concrete Class |
|---|---|---|
| Instantiation | ❌ No | ✅ Yes |
| Abstract methods | Allowed | ❌ Not allowed |
| Implementation | Partial | Full |
| Use case | Base design | Actual object |
Abstract Class vs Interface (Quick Preview)
| Feature | Abstract Class | Interface |
|---|---|---|
| Methods | Abstract + concrete | Abstract (default allowed) |
| Variables | Instance variables | Constants only |
| Constructors | Yes | No |
| Multiple inheritance | ❌ No | ✅ Yes |
| Use case | IS-A relationship | Capability/contract |
When to Use Abstract Classes
- When classes share common state and behavior
- When partial implementation is needed
- When you want to provide base functionality
- When multiple related classes exist
When NOT to Use Abstract Classes
- When multiple inheritance is required
- When only method contracts are needed
- When no common code exists
Common Beginner Mistakes
- Trying to create object of abstract class
- Forgetting to implement abstract methods
- Confusing abstract class with interface
- Using abstract class where interface is better
- Overusing abstraction
Additional Abstract Class Examples (20 Scenarios)
1. Abstract Class with Multiple Abstract Methods
abstract class Device {
abstract void powerOn();
abstract void powerOff();
}
class Phone extends Device {
void powerOn() { System.out.println("Phone ON"); }
void powerOff() { System.out.println("Phone OFF"); }
public static void main(String[] args) {
Device d = new Phone();
d.powerOn();
d.powerOff();
}
}
Output
Phone ON
Phone OFF
2. Abstract Class with State (Fields)
abstract class Account {
double balance;
abstract void deposit(double amt);
}
class Savings extends Account {
void deposit(double amt) {
balance += amt;
}
public static void main(String[] args) {
Account a = new Savings();
a.deposit(500);
System.out.println(a.balance);
}
}
Output
500.0
3. Abstract Class with Protected Members
abstract class Base {
protected int x = 10;
abstract void show();
}
class Child extends Base {
void show() { System.out.println(x); }
public static void main(String[] args) {
new Child().show();
}
}
Output
10
4. Abstract Method Implementation Across Levels
abstract class A {
abstract void m();
}
abstract class B extends A {
// still abstract
}
class C extends B {
void m() { System.out.println("Implemented"); }
public static void main(String[] args) {
new C().m();
}
}
Output
Implemented
5. Abstract Class with Template Method Pattern
abstract class Report {
final void generate() {
header();
body();
footer();
}
void header() { System.out.println("Header"); }
abstract void body();
void footer() { System.out.println("Footer"); }
}
class SalesReport extends Report {
void body() { System.out.println("Sales Data"); }
public static void main(String[] args) {
new SalesReport().generate();
}
}
Output
Header
Sales Data
Footer
6. Abstract Class Constructor with Parameters
abstract class User {
String role;
User(String role) {
this.role = role;
}
}
class Admin extends User {
Admin() {
super("ADMIN");
}
public static void main(String[] args) {
System.out.println(new Admin().role);
}
}
Output
ADMIN
7. Abstract Class Returning Abstract Type
abstract class Shape {
abstract String name();
}
class Circle extends Shape {
String name() { return "Circle"; }
}
class Test {
static Shape create() {
return new Circle();
}
public static void main(String[] args) {
System.out.println(create().name());
}
}
Output
Circle
8. Abstract Class with Static Method
abstract class Util {
static void help() {
System.out.println("Helping");
}
}
class Test {
public static void main(String[] args) {
Util.help();
}
}
Output
Helping
9. Abstract Class with Instance Block
abstract class A {
{
System.out.println("Instance Block");
}
}
class B extends A {
B() { System.out.println("Constructor"); }
public static void main(String[] args) {
new B();
}
}
Output
Instance Block
Constructor
10. Overriding Abstract Method with Broader Access
abstract class A {
protected abstract void show();
}
class B extends A {
public void show() { System.out.println("Shown"); }
public static void main(String[] args) {
new B().show();
}
}
Output
Shown
11. Abstract Class vs Interface (State Difference)
abstract class Counter {
int count;
abstract void inc();
}
class Impl extends Counter {
void inc() { count++; }
public static void main(String[] args) {
Counter c = new Impl();
c.inc();
System.out.println(c.count);
}
}
Output
1
12. Abstract Method Cannot Be Static
abstract class A {
// abstract static void m(); // ❌ Compile-time error
}
Explanation
Abstract methods need instance context.
13. Abstract Class with Final Field
abstract class Config {
final String ENV = "PROD";
}
class App extends Config {
public static void main(String[] args) {
System.out.println(new App().ENV);
}
}
Output
PROD
14. Partial Implementation of Interface via Abstract Class
interface Ops {
void a();
void b();
}
abstract class BaseOps implements Ops {
public void a() { System.out.println("A"); }
}
class FullOps extends BaseOps {
public void b() { System.out.println("B"); }
public static void main(String[] args) {
Ops o = new FullOps();
o.a();
o.b();
}
}
Output
A
B
15. Abstract Class with Covariant Return
abstract class Factory {
abstract Number create();
}
class IntFactory extends Factory {
Integer create() { return 10; }
public static void main(String[] args) {
System.out.println(new IntFactory().create());
}
}
Output
10
16. Abstract Class and instanceof
abstract class A {}
class B extends A {}
class Test {
public static void main(String[] args) {
A a = new B();
System.out.println(a instanceof A);
System.out.println(a instanceof B);
}
}
Output
true
true
17. Abstract Class Cannot Be Final
// final abstract class A {} // ❌ Compile-time error
Explanation
final prevents inheritance; abstract requires it.
18. Abstract Class with Synchronized Method
abstract class Service {
synchronized void ping() {
System.out.println("Ping");
}
}
class Impl extends Service {
public static void main(String[] args) {
new Impl().ping();
}
}
Output
Ping
19. Real-World Abstraction (Payment Gateway)
abstract class PaymentGateway {
abstract boolean pay(double amount);
}
class Stripe extends PaymentGateway {
boolean pay(double amount) {
System.out.println("Stripe: " + amount);
return true;
}
public static void main(String[] args) {
PaymentGateway pg = new Stripe();
pg.pay(99.99);
}
}
Output
Stripe: 99.99
20. Interview Summary – Abstract Classes
abstract class A {
abstract void run();
}
class B extends A {
void run() { System.out.println("Running"); }
public static void main(String[] args) {
A a = new B();
a.run();
}
}
Key Points
- Cannot instantiate
- Can have state, constructors, concrete methods
- Enables partial abstraction
Output
Running
Interview-Ready Answers
Short Answer
An abstract class is a class that cannot be instantiated and may contain abstract and concrete methods.
Detailed Answer
In Java, an abstract class is used to achieve abstraction by providing partial implementation. It can contain abstract methods that must be implemented by subclasses and concrete methods with shared logic. Abstract classes support inheritance and polymorphism.
Key Takeaway
Abstract classes define a base blueprint with shared behavior and mandatory methods. They are ideal when you need partial abstraction with code reuse.