Java Abstract Classes & Methods
Learn abstract classes and abstract methods in Java: when to use them, how they differ from interfaces and concrete classes, and the template method pattern—with short, readable examples.
1. Introduction to Abstract Classes
An abstract class cannot be instantiated with new. It is meant to be extended by subclasses. It may contain both concrete methods (with a body) and abstract methods (no body—subclasses must implement them).
- Declared with the
abstractkeyword - Can have fields, constructors, and implemented methods
- Forces subclasses to complete unfinished behavior
- Supports polymorphism:
Animal a = new Dog();
Think of an abstract class as a partial blueprint: common parts are built in; specific parts are left for each subclass.
abstract class Animal {
String name;
Animal(String name) { this.name = name; }
void eat() { System.out.println(name + " is eating"); }
abstract void makeSound(); // no body
}
class Dog extends Animal {
Dog(String name) { super(name); }
@Override void makeSound() { System.out.println("Woof!"); }
}
// Animal a = new Animal("X"); // ERROR
Animal dog = new Dog("Buddy");
dog.makeSound();
2. Abstract Methods
An abstract method has no implementation. It ends with a semicolon and must be overridden in every concrete subclass.
- Only allowed inside an abstract class (or interface)
- Cannot be
private,static, orfinal - Subclasses must implement all inherited abstract methods
abstract class Shape {
abstract double getArea();
abstract void draw();
}
class Circle extends Shape {
double radius;
Circle(double r) { radius = r; }
@Override double getArea() { return Math.PI * radius * radius; }
@Override void draw() { System.out.println("Drawing circle"); }
}
abstract.
3. Abstract vs Concrete Classes
A concrete class can be instantiated and must implement all abstract methods from its parents. An abstract class acts as a shared base with optional partial implementation.
| Feature | Abstract Class | Concrete Class |
|---|---|---|
| Keyword | abstract class | class |
| Instantiation | Not allowed | new MyClass() |
| Abstract methods | Allowed | Not allowed |
| Purpose | Base / template | Full implementation |
abstract class Employee {
protected String name;
abstract double calculateSalary();
void display() { System.out.println(name); }
}
class Manager extends Employee {
@Override double calculateSalary() { return 80000; }
}
4. Template Method Pattern
The template method pattern defines the steps of an algorithm in a base class and lets subclasses fill in specific steps. The template method is often final so the overall flow cannot change.
abstract class DataProcessor {
public final void process() {
readData();
transformData();
saveData();
}
abstract void readData();
void transformData() { /* optional hook */ }
abstract void saveData();
}
class CSVProcessor extends DataProcessor {
@Override void readData() { System.out.println("Read CSV"); }
@Override void saveData() { System.out.println("Save CSV"); }
}
5. Abstract Class vs Interface
Use an interface for a contract (what a class can do). Use an abstract class when related classes share code and state.
| Feature | Abstract Class | Interface |
|---|---|---|
| Inheritance | Single (extends) | Multiple (implements) |
| Fields | Instance variables | Constants only (traditionally) |
| Constructors | Yes | No |
| Best for | Shared code + IS-A | Capabilities / CAN-DO |
interface Flyable { void fly(); }
abstract class Bird implements Flyable {
protected String species;
Bird(String species) { this.species = species; }
}
class Sparrow extends Bird {
Sparrow() { super("Sparrow"); }
@Override public void fly() { System.out.println("Flying"); }
}
6. Real-world Use Cases
Frameworks often use abstract classes: HttpServlet, Thread, JDBC drivers, and game engines define a fixed flow with overridable hooks.
Database connection template
abstract class DatabaseConnection {
public final void executeQuery(String sql) {
connect();
runQuery(sql);
disconnect();
}
abstract void connect();
abstract void runQuery(String sql);
abstract void disconnect();
}
Payment processing
abstract class PaymentProcessor {
public final boolean pay(double amount) {
if (!validate(amount)) return false;
return charge(amount);
}
boolean validate(double amount) { return amount > 0; }
abstract boolean charge(double amount);
}
7. Best Practices & Common Mistakes
Do
- Use abstract classes for true IS-A relationships with shared code
- Keep the number of abstract methods reasonable
- Make template methods
finalwhen the algorithm must not change - Prefer interfaces when you only need a contract
Avoid
- Trying to instantiate an abstract class
- Leaving abstract methods unimplemented in concrete subclasses
- Declaring
private abstractorstatic abstractmethods - Deep inheritance trees that are hard to maintain
// Poor: unrelated abstract methods
abstract class Bad { abstract void fly(); abstract void saveToDb(); }
// Better: focused contract
abstract class Good {
abstract void performTask();
protected void log(String msg) { System.out.println(msg); }
}
8. Practice Exercises
- Create abstract class
Documentwithload(),save(), and afinal process()template method. ImplementTextDocumentandPDFDocument. - Build abstract
Notificationwithsend(); addEmailNotificationandSMSNotification. - Design abstract
GameCharacterwithattack()and sharedmove(); subclassWarriorandMage.
9. Summary & Quick Reference
| Concept | Syntax | Notes |
|---|---|---|
| Abstract class | abstract class X { } | Cannot use new |
| Abstract method | abstract void m(); | No body; must override |
| Template method | final void run() { ... } | Fixed algorithm in base class |
| Polymorphism | Shape s = new Circle(); | Reference type = abstract/base |
Key takeaways
- Abstract classes share code and enforce structure for related types.
- Interfaces define what a class can do; abstract classes define what it is.
- Template methods give you reusable algorithms with customizable steps.