00:00

Abstract Class in Java – Abstract Methods, Rules and Examples

An abstract class is a class declared with the abstract keyword. It cannot be instantiated on its own; it exists to be extended. It can contain abstract methods (declared without a body, which subclasses must implement) alongside ordinary fields, constructors and concrete methods that all subclasses share.

This tutorial covers the syntax and rules of abstract classes and methods, shows constructors, anonymous subclasses and skeletal implementations in action, and explains when an interface is the better choice.

1. Syntax

Syntax
abstract class ClassName {
    // fields, constructors, static members, blocks
    // concrete (normal) methods
    abstract ReturnType methodName(Parameters);   // no body, ends with ;
}

An abstract class can contain everything a normal class can, plus abstract methods. If a class has even one abstract method, it must be declared abstract.

2. A Complete Example

Every employee has a name and a payslip, but each type calculates monthly pay differently:

AbstractClassBasics.java
public class AbstractClassBasics {
    static abstract class Employee {
        private final String name;           // fields
        protected final double baseSalary;
        private static int count = 0;

        Employee(String name, double baseSalary) {   // constructor
            this.name = name;
            this.baseSalary = baseSalary;
            count++;
            System.out.println("Employee constructor ran for " + name);
        }

        abstract double monthlyPay();        // abstract: no body

        String payslip() {                   // concrete method using the abstract one
            return String.format("%-6s %-10s %,10.2f", name, getClass().getSimpleName(), monthlyPay());
        }

        static int count() { return count; } // static method
    }

    static class FullTime extends Employee {
        FullTime(String name, double salary) { super(name, salary); }
        @Override double monthlyPay() { return baseSalary / 12; }
    }

    static class Contractor extends Employee {
        private final int hours;
        Contractor(String name, double hourlyRate, int hours) { super(name, hourlyRate); this.hours = hours; }
        @Override double monthlyPay() { return baseSalary * hours; }
    }

    public static void main(String[] args) {
        Employee[] staff = { new FullTime("Asha", 1_200_000), new Contractor("Ravi", 900, 120) };
        System.out.println();
        for (Employee e : staff) System.out.println(e.payslip());
        System.out.println("Employees created: " + Employee.count());
    }
}
Output
Employee constructor ran for Asha
Employee constructor ran for Ravi

Asha   FullTime   100,000.00
Ravi   Contractor 108,000.00
Employees created: 2
  • Employee has fields, a constructor, a static method and a concrete payslip() method.
  • monthlyPay() is abstract; each subclass provides its own formula.
  • payslip() calls monthlyPay(), and polymorphism picks the right version at run time.
  • The abstract class's constructor runs, through super(...), every time a subclass object is created.

3. Abstract Methods

An abstract method declares the signature (return type, name, parameters and optional throws clause) and ends with a semicolon:

Abstract method rules
abstract class Order {
    abstract String summary(int orderId) throws OrderNotFoundException;  // OK
}

class Invoice {
    abstract void print();      // compile error: Invoice is not abstract
}

abstract class Bad {
    private abstract void a();  // error: private methods cannot be overridden
    static abstract void b();   // error: static methods cannot be overridden
    final abstract void c();    // error: final methods cannot be overridden
}

4. Instantiating Through Anonymous Subclasses

new Greeter() is illegal for an abstract class, but an anonymous class that implements the abstract methods is allowed:

AnonymousSubclass.java
public class AnonymousSubclass {
    static abstract class Greeter {
        abstract String greet(String name);
        void welcome(String name) { System.out.println(greet(name) + " Welcome to JavaByTechie."); }
    }

    public static void main(String[] args) {
        // An abstract class cannot be instantiated, but an anonymous subclass can be
        Greeter hindi = new Greeter() {
            @Override String greet(String name) { return "Namaste, " + name + "!"; }
        };
        hindi.welcome("Asha");
        System.out.println("Actual class is anonymous: " + hindi.getClass().isAnonymousClass());
    }
}
Output
Namaste, Asha! Welcome to JavaByTechie.
Actual class is anonymous: true

5. Partially Implementing an Abstract Class

A subclass that does not implement every abstract method must itself be declared abstract. The chain ends with a concrete class that completes the contract:

AbstractChain.java
public class AbstractChain {
    static abstract class Vehicle {
        abstract int wheels();
        abstract String fuel();
    }

    // Still abstract: implements only part of the contract
    static abstract class Car extends Vehicle {
        @Override int wheels() { return 4; }
    }

    static class ElectricCar extends Car {
        @Override String fuel() { return "electricity"; }
    }

    public static void main(String[] args) {
        Vehicle v = new ElectricCar();
        System.out.println("Wheels: " + v.wheels() + ", fuel: " + v.fuel());
    }
}
Output
Wheels: 4, fuel: electricity

6. Abstract Class + Interface: Skeletal Implementation

A powerful pattern is to define the contract as an interface and provide an abstract class that implements the shared parts. The JDK does this with List/AbstractList and Map/AbstractMap:

AbstractWithInterface.java
public class AbstractWithInterface {
    interface PaymentMethod {
        boolean pay(double amount);
    }

    // Skeletal implementation: shared validation and logging, one step left abstract
    static abstract class AbstractPayment implements PaymentMethod {
        @Override
        public final boolean pay(double amount) {
            if (amount <= 0) {
                System.out.println("Invalid amount: " + amount);
                return false;
            }
            boolean ok = process(amount);
            System.out.println(getClass().getSimpleName() + " " + amount + " -> " + (ok ? "SUCCESS" : "FAILED"));
            return ok;
        }
        protected abstract boolean process(double amount);
    }

    static class UpiPayment extends AbstractPayment {
        protected boolean process(double amount) { return true; }
    }
    static class CardPayment extends AbstractPayment {
        protected boolean process(double amount) { return amount <= 50_000; }   // card limit
    }

    public static void main(String[] args) {
        PaymentMethod upi = new UpiPayment(), card = new CardPayment();
        upi.pay(1_499);
        card.pay(75_000);
        card.pay(-5);
    }
}
Output
UpiPayment 1499.0 -> SUCCESS
CardPayment 75000.0 -> FAILED
Invalid amount: -5.0

The final pay method is a template method: validation and logging are fixed, and only process varies.

7. Rules of Abstract Classes

  • Declared with the abstract keyword; cannot be instantiated with new.
  • Can have zero or more abstract methods, and any number of concrete methods.
  • Can have constructors, instance and static fields, static methods, and initializer blocks.
  • Can have members with any access modifier, unlike interface methods.
  • A concrete subclass must implement all inherited abstract methods.
  • Cannot be final, because it must be extendable.
  • Can implement interfaces without implementing their methods; subclasses complete them.
  • Can be used as a reference type: Employee e = new FullTime(...);

8. Abstract Class vs Interface

AspectAbstract classInterface
MethodsAbstract and concreteAbstract, default, static and private
FieldsAny instance or static fieldsOnly public static final constants
ConstructorsYesNo
InheritanceA class extends only oneA class implements many
Access modifiersAnyMembers are public (private helper methods allowed)
Best forRelated classes sharing state and codeCapabilities shared by unrelated classes

Read the full comparison in Abstract Class vs Interface.

9. Summary

  • An abstract class is declared with abstract and cannot be instantiated.
  • Abstract methods have no body and must be implemented by concrete subclasses.
  • Abstract classes can have fields, constructors and concrete methods shared by subclasses.
  • Abstract methods cannot be private, static or final; an abstract class cannot be final.
  • Combine an interface with an abstract skeletal implementation for flexible, reusable designs.

Related Tutorials